| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package com.ruoyi.app.mendian;
- import com.ruoyi.common.annotation.Anonymous;
- import com.ruoyi.common.utils.MessageUtils;
- import com.ruoyi.system.domain.PosFood;
- import com.ruoyi.system.service.IPosFoodService;
- import com.ruoyi.system.service.MerchantStoreAccessService;
- import com.ruoyi.system.utils.Auth;
- import org.junit.jupiter.api.AfterEach;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import org.mockito.ArgumentCaptor;
- import org.mockito.MockedStatic;
- import org.springframework.http.MediaType;
- import org.springframework.security.access.prepost.PreAuthorize;
- import org.springframework.test.util.ReflectionTestUtils;
- import org.springframework.test.web.servlet.MockMvc;
- import org.springframework.test.web.servlet.setup.MockMvcBuilders;
- import org.springframework.web.bind.annotation.PutMapping;
- import java.lang.reflect.Method;
- import java.util.Arrays;
- import static org.junit.jupiter.api.Assertions.*;
- import static org.mockito.ArgumentMatchers.any;
- import static org.mockito.ArgumentMatchers.anyString;
- import static org.mockito.Mockito.*;
- import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
- import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
- /** 平台审核独立于商家 token/门店归属,只更新审核状态,不能误走商品保存或规格处理。 */
- class PosFoodControllerAuditTest {
- private IPosFoodService foods;
- private MerchantStoreAccessService merchantAccess;
- private MockMvc mvc;
- private MockedStatic<MessageUtils> messages;
- @BeforeEach
- void setup() {
- messages = mockStatic(MessageUtils.class);
- messages.when(() -> MessageUtils.message(anyString())).thenAnswer(call -> call.getArgument(0));
- PosFoodController controller = new PosFoodController();
- foods = mock(IPosFoodService.class);
- merchantAccess = mock(MerchantStoreAccessService.class);
- ReflectionTestUtils.setField(controller, "posFoodService", foods);
- ReflectionTestUtils.setField(controller, "merchantStoreAccessService", merchantAccess);
- mvc = MockMvcBuilders.standaloneSetup(controller).build();
- when(foods.updatePosFood(any(PosFood.class))).thenReturn(1);
- }
- @AfterEach
- void cleanup() { messages.close(); }
- @Test
- void platformAuditUsesExistingEditPermissionAndNeverMerchantAuth() {
- Method audit = Arrays.stream(PosFoodController.class.getDeclaredMethods())
- .filter(method -> method.isAnnotationPresent(PutMapping.class)
- && Arrays.asList(method.getAnnotation(PutMapping.class).value()).contains("/audit"))
- .findFirst().orElse(null);
- assertNotNull(audit, "platform audit endpoint must exist");
- assertNotNull(audit.getAnnotation(PreAuthorize.class));
- assertEquals("@ss.hasPermi('chanting:food:edit')", audit.getAnnotation(PreAuthorize.class).value());
- assertNull(audit.getAnnotation(Anonymous.class));
- assertNull(audit.getAnnotation(Auth.class));
- }
- @Test
- void approveAndRevokeWorkWithoutMerchantTokenHeader() throws Exception {
- for (String state : new String[] {"1", "0"}) {
- mvc.perform(put("/chanting/food/audit").header("Authorization", "Bearer platform-test")
- .contentType(MediaType.APPLICATION_JSON).content("{\"id\":9137,\"toExamine\":\"" + state + "\"}"))
- .andExpect(status().isOk()).andExpect(jsonPath("$.code").value(200));
- }
- ArgumentCaptor<PosFood> update = ArgumentCaptor.forClass(PosFood.class);
- verify(foods, times(2)).updatePosFood(update.capture());
- assertEquals("1", update.getAllValues().get(0).getToExamine());
- assertEquals("0", update.getAllValues().get(1).getToExamine());
- verifyNoInteractions(merchantAccess);
- verify(foods, never()).saveOrUpdate(any(PosFood.class));
- }
- @Test
- void auditIgnoresInjectedContentAndNeverChangesStoreOrSpecs() throws Exception {
- mvc.perform(put("/chanting/food/audit").contentType(MediaType.APPLICATION_JSON)
- .content("{\"id\":9137,\"toExamine\":\"1\",\"mdid\":999,\"price\":1,\"name\":\"injected\",\"stackingUp\":\"0\",\"foodSpecs\":[]}"))
- .andExpect(status().isOk()).andExpect(jsonPath("$.code").value(200));
- ArgumentCaptor<PosFood> update = ArgumentCaptor.forClass(PosFood.class);
- verify(foods).updatePosFood(update.capture());
- PosFood changed = update.getValue();
- assertEquals(9137L, changed.getId());
- assertEquals("1", changed.getToExamine());
- assertNull(changed.getMdid());
- assertNull(changed.getPrice());
- assertNull(changed.getName());
- assertNull(changed.getStackingUp());
- assertNull(changed.getFoodSpecs());
- assertNull(changed.getRecommend());
- }
- @Test
- void invalidIdOrAuditStateIsRejectedBeforeWrite() throws Exception {
- for (String payload : new String[] {"{}", "{\"id\":0,\"toExamine\":\"1\"}",
- "{\"id\":-1,\"toExamine\":\"1\"}", "{\"id\":9137}",
- "{\"id\":9137,\"toExamine\":\"2\"}", "{\"id\":9137,\"toExamine\":\"\"}"}) {
- mvc.perform(put("/chanting/food/audit").contentType(MediaType.APPLICATION_JSON).content(payload))
- .andExpect(status().isOk()).andExpect(jsonPath("$.code").value(500))
- .andExpect(jsonPath("$.msg").value("food.audit.invalid"));
- }
- verifyNoInteractions(foods);
- }
- @Test
- void missingFoodDoesNotCreateProductOrReportSuccess() throws Exception {
- when(foods.updatePosFood(any(PosFood.class))).thenReturn(0);
- mvc.perform(put("/chanting/food/audit").contentType(MediaType.APPLICATION_JSON)
- .content("{\"id\":9137,\"toExamine\":\"1\"}"))
- .andExpect(status().isOk()).andExpect(jsonPath("$.code").value(500));
- verify(foods, never()).saveOrUpdate(any(PosFood.class));
- }
- @Test
- void originalMerchantEndpointStillRequiresMerchantToken() throws Exception {
- mvc.perform(put("/chanting/food/changerecommend").header("Authorization", "Bearer platform-test")
- .contentType(MediaType.APPLICATION_JSON).content("{\"id\":9137,\"toExamine\":\"1\"}"))
- .andExpect(status().isBadRequest());
- verifyNoInteractions(foods, merchantAccess);
- }
- }
|