| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- package com.ruoyi.app.flashdelivery.controller;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryCreateRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryOrderDetailView;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryProofRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryDeliverRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryStopDeliverRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryQuoteView;
- import com.ruoyi.app.flashdelivery.exception.FlashDeliveryQuoteChangedException;
- import com.ruoyi.app.flashdelivery.service.FlashDeliveryApplicationService;
- import com.ruoyi.common.core.domain.AjaxResult;
- import com.ruoyi.common.utils.spring.SpringUtils;
- import org.junit.jupiter.api.AfterAll;
- import org.junit.jupiter.api.BeforeAll;
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.support.DefaultListableBeanFactory;
- import org.springframework.context.support.StaticMessageSource;
- import org.springframework.security.access.prepost.PreAuthorize;
- import org.springframework.test.util.ReflectionTestUtils;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestHeader;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.GetMapping;
- import com.ruoyi.common.annotation.Log;
- import com.ruoyi.system.utils.Auth;
- import com.ruoyi.system.utils.JwtUtil;
- import java.lang.reflect.Method;
- import java.math.BigDecimal;
- import static org.junit.jupiter.api.Assertions.assertArrayEquals;
- import static org.junit.jupiter.api.Assertions.assertNotNull;
- import static org.junit.jupiter.api.Assertions.assertSame;
- import static org.junit.jupiter.api.Assertions.assertThrows;
- import static org.junit.jupiter.api.Assertions.assertTrue;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- class FlashDeliveryControllerContractTest {
- @Test
- void newStopDeliveryAcceptsAllBusinessParametersInBody() throws Exception {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- var mvc = org.springframework.test.web.servlet.setup.MockMvcBuilders
- .standaloneSetup(new FlashDeliveryRiderController(service)).build();
- mvc.perform(org.springframework.test.web.servlet.request.MockMvcRequestBuilders
- .post("/system/flashDelivery/rider/orders/stops/deliver")
- .header("token", JwtUtil.token("8", "rider"))
- .contentType(org.springframework.http.MediaType.APPLICATION_JSON)
- .content("{\"orderId\":10,\"stopId\":13,\"pinCode\":\"1111\",\"imageUrls\":[\"/profile/d.jpg\"]}"))
- .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().isOk());
- var request = org.mockito.ArgumentCaptor.forClass(FlashDeliveryDeliverRequest.class);
- verify(service).deliverAtStop(org.mockito.ArgumentMatchers.eq(8L), org.mockito.ArgumentMatchers.eq(10L),
- org.mockito.ArgumentMatchers.eq(13L), request.capture());
- org.junit.jupiter.api.Assertions.assertEquals("1111", request.getValue().getPinCode());
- org.junit.jupiter.api.Assertions.assertEquals(java.util.List.of("/profile/d.jpg"), request.getValue().getImageUrls());
- org.junit.jupiter.api.Assertions.assertEquals(13L, request.getValue().getStopId());
- }
- @Test
- void newStopDeliveryRejectsMissingOrNonPositiveBodyIds() throws Exception {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- var mvc = org.springframework.test.web.servlet.setup.MockMvcBuilders
- .standaloneSetup(new FlashDeliveryRiderController(service))
- .setControllerAdvice(new com.ruoyi.framework.web.exception.GlobalExceptionHandler()).build();
- for (String body : java.util.List.of("{}", "{\"orderId\":0,\"stopId\":13}",
- "{\"orderId\":-1,\"stopId\":13}", "{\"orderId\":10}",
- "{\"orderId\":10,\"stopId\":0}", "{\"orderId\":10,\"stopId\":-1}")) {
- mvc.perform(org.springframework.test.web.servlet.request.MockMvcRequestBuilders
- .post("/system/flashDelivery/rider/orders/stops/deliver")
- .header("token", JwtUtil.token("8", "rider"))
- .contentType(org.springframework.http.MediaType.APPLICATION_JSON).content(body))
- .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().isOk())
- .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.code").value(500));
- }
- org.mockito.Mockito.verifyNoInteractions(service);
- }
- @Test
- void newV2EndpointsUseBodyDtosAndHeaderAuthentication() throws Exception {
- for (Method method : java.util.List.of(
- FlashDeliveryUserController.class.getMethod("quoteV2", String.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryV2QuoteRequest.class),
- FlashDeliveryUserController.class.getMethod("createV2", String.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryV2CreateRequest.class),
- FlashDeliveryUserController.class.getMethod("quoteAddressV2", String.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryV2AddressChangeRequest.class),
- FlashDeliveryUserController.class.getMethod("updateAddressV2", String.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryV2AddressConfirmRequest.class),
- FlashDeliveryRiderController.class.getMethod("deliverAtStop", String.class,
- FlashDeliveryStopDeliverRequest.class))) {
- assertNotNull(method.getAnnotation(Auth.class));
- assertNotNull(method.getParameters()[0].getAnnotation(RequestHeader.class));
- assertNotNull(method.getParameters()[1].getAnnotation(RequestBody.class));
- org.junit.jupiter.api.Assertions.assertEquals(2, method.getParameterCount());
- assertTrue(java.util.Arrays.stream(method.getAnnotation(org.springframework.web.bind.annotation.PostMapping.class)
- .value()).noneMatch(path -> path.contains("{")));
- }
- }
- @Test
- void perStopFulfilmentUsesTokenExplicitPathsAndBodyDtos() throws Exception {
- for (Method method : java.util.List.of(
- FlashDeliveryRiderController.class.getMethod("pickupStop", String.class, Long.class, Long.class, FlashDeliveryProofRequest.class),
- FlashDeliveryRiderController.class.getMethod("target", String.class, Long.class, Long.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryTargetRequest.class))) {
- assertNotNull(method.getAnnotation(Auth.class));
- assertNotNull(method.getParameters()[0].getAnnotation(RequestHeader.class));
- assertNotNull(method.getParameters()[1].getAnnotation(org.springframework.web.bind.annotation.PathVariable.class));
- assertNotNull(method.getParameters()[2].getAnnotation(org.springframework.web.bind.annotation.PathVariable.class));
- assertNotNull(method.getParameters()[3].getAnnotation(RequestBody.class));
- }
- }
- private static ConfigurableListableBeanFactory originalBeanFactory;
- @BeforeAll
- static void initializeMessages() {
- originalBeanFactory = (ConfigurableListableBeanFactory)
- ReflectionTestUtils.getField(SpringUtils.class, "beanFactory");
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- StaticMessageSource messageSource = new StaticMessageSource();
- messageSource.setUseCodeAsDefaultMessage(true);
- beanFactory.registerSingleton("messageSource", messageSource);
- new SpringUtils().postProcessBeanFactory(beanFactory);
- }
- @AfterAll
- static void restoreMessages() {
- new SpringUtils().postProcessBeanFactory(originalBeanFactory);
- }
- @Test
- void waitingOrderEditingEndpointsExistAndUseExplicitAuthenticatedDtos() {
- java.util.Set<String> paths = new java.util.HashSet<>();
- for (Method method : FlashDeliveryUserController.class.getDeclaredMethods()) {
- var post = method.getAnnotation(org.springframework.web.bind.annotation.PostMapping.class);
- if (post == null) continue;
- for (String path : post.value()) {
- if (!java.util.Set.of("/orders/{id}/address/quote", "/orders/address", "/orders/tip").contains(path)) continue;
- paths.add(path);
- assertNotNull(method.getAnnotation(Auth.class));
- assertNotNull(method.getParameters()[0].getAnnotation(RequestHeader.class));
- int bodyIndex;
- if (path.endsWith("/quote")) {
- bodyIndex = 2;
- assertNotNull(method.getParameters()[1].getAnnotation(org.springframework.web.bind.annotation.PathVariable.class));
- } else {
- org.junit.jupiter.api.Assertions.assertEquals(2, method.getParameterCount());
- bodyIndex = 1;
- }
- assertNotNull(method.getParameters()[bodyIndex].getAnnotation(RequestBody.class));
- assertTrue(!java.util.Map.class.isAssignableFrom(method.getParameters()[bodyIndex].getType()));
- }
- }
- assertTrue(paths.containsAll(java.util.Set.of("/orders/{id}/address/quote",
- "/orders/address", "/orders/tip")), "Missing waiting-order editing endpoints");
- }
- @Test
- void appControllersReadIdentityFromTokenAndUseRequestBodies() throws Exception {
- Method create = FlashDeliveryUserController.class.getMethod("create", String.class,
- FlashDeliveryCreateRequest.class);
- assertNotNull(create.getParameters()[0].getAnnotation(RequestHeader.class));
- assertNotNull(create.getParameters()[1].getAnnotation(RequestBody.class));
- Method pickup = FlashDeliveryRiderController.class.getMethod("pickup", String.class,
- Long.class, FlashDeliveryProofRequest.class);
- assertNotNull(pickup.getParameters()[0].getAnnotation(RequestHeader.class));
- assertNotNull(pickup.getParameters()[2].getAnnotation(RequestBody.class));
- Method deliver = FlashDeliveryRiderController.class.getMethod("deliver", String.class,
- Long.class, FlashDeliveryDeliverRequest.class);
- assertNotNull(deliver.getParameters()[2].getAnnotation(RequestBody.class));
- }
- @Test
- void appOrderListsUseSimplePageAndRiderFoodOrderParameters() throws Exception {
- Method userOrders = FlashDeliveryUserController.class.getMethod("orders",
- String.class, int.class, int.class, String.class);
- assertNotNull(userOrders.getParameters()[0].getAnnotation(RequestHeader.class));
- assertNotNull(userOrders.getParameters()[1].getAnnotation(RequestParam.class));
- assertNotNull(userOrders.getParameters()[2].getAnnotation(RequestParam.class));
- assertNotNull(userOrders.getParameters()[3].getAnnotation(RequestParam.class));
- assertTrue(!userOrders.getParameters()[3].getAnnotation(RequestParam.class).required());
- Method riderOrders = FlashDeliveryRiderController.class.getMethod("orders",
- String.class, int.class, int.class, String.class, BigDecimal.class, BigDecimal.class);
- assertArrayEquals(new String[]{"/orders"}, riderOrders.getAnnotation(GetMapping.class).value());
- for (int index = 1; index < riderOrders.getParameterCount(); index++) {
- assertNotNull(riderOrders.getParameters()[index].getAnnotation(RequestParam.class));
- }
- assertThrows(NoSuchMethodException.class,
- () -> FlashDeliveryRiderController.class.getMethod("available",
- String.class, int.class, int.class, String.class));
- assertThrows(NoSuchMethodException.class,
- () -> FlashDeliveryRiderController.class.getMethod("mine",
- String.class, int.class, int.class, String.class, String.class));
- }
- @Test
- void riderOrderCountEndpointUsesOptionalCoordinatesAndReturnsCounts() throws Exception {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- var counts = new com.ruoyi.app.flashdelivery.dto.FlashDeliveryRiderOrderCountView();
- when(service.riderOrderCounts(8L, BigDecimal.ONE, BigDecimal.TEN)).thenReturn(counts);
- AjaxResult result = new FlashDeliveryRiderController(service)
- .orderCount(JwtUtil.token("8", "rider"), BigDecimal.ONE, BigDecimal.TEN);
- assertSame(counts, result.get(AjaxResult.DATA_TAG));
- Method orderCount = FlashDeliveryRiderController.class.getMethod("orderCount",
- String.class, BigDecimal.class, BigDecimal.class);
- assertArrayEquals(new String[]{"/orderCount"}, orderCount.getAnnotation(GetMapping.class).value());
- assertNotNull(orderCount.getParameters()[0].getAnnotation(RequestHeader.class));
- for (int index = 1; index < orderCount.getParameterCount(); index++) {
- assertTrue(!orderCount.getParameters()[index].getAnnotation(RequestParam.class).required());
- }
- }
- @Test
- void appDetailAndAcceptPutDirectOrderDtoInAjaxData() {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- FlashDeliveryOrderDetailView detail = new FlashDeliveryOrderDetailView();
- detail.setId(10L);
- when(service.userDetail(7L, 10L)).thenReturn(detail);
- when(service.riderDetail(8L, 10L)).thenReturn(detail);
- when(service.accept(8L, 10L)).thenReturn(detail);
- AjaxResult userResult = new FlashDeliveryUserController(service)
- .detail(JwtUtil.token("7", "user"), 10L);
- AjaxResult riderResult = new FlashDeliveryRiderController(service)
- .detail(JwtUtil.token("8", "rider"), 10L);
- AjaxResult acceptResult = new FlashDeliveryRiderController(service)
- .accept(JwtUtil.token("8", "rider"), 10L);
- assertSame(detail, userResult.get(AjaxResult.DATA_TAG));
- assertSame(detail, riderResult.get(AjaxResult.DATA_TAG));
- assertSame(detail, acceptResult.get(AjaxResult.DATA_TAG));
- }
- @Test
- void editingEndpointsReturnServiceQuoteAndUpdatedDetails() throws Exception {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- var change = new com.ruoyi.app.flashdelivery.dto.FlashDeliveryAddressChangeRequest();
- var json = new com.fasterxml.jackson.databind.ObjectMapper();
- var confirmation = json.readValue("{\"orderId\":10,\"orderVersion\":2}",
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryAddressConfirmRequest.class);
- var tip = json.readValue("{\"orderId\":10,\"orderVersion\":2,\"additionalTipAmount\":20}",
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryTipAddRequest.class);
- FlashDeliveryQuoteView quote = new FlashDeliveryQuoteView();
- FlashDeliveryOrderDetailView detail = new FlashDeliveryOrderDetailView();
- when(service.quoteAddress(7L, 10L, change)).thenReturn(quote);
- when(service.updateAddress(7L, 10L, confirmation)).thenReturn(detail);
- when(service.addTip(7L, 10L, tip)).thenReturn(detail);
- var controller = new FlashDeliveryUserController(service);
- String token = JwtUtil.token("7", "user");
- assertSame(quote, controller.quoteAddress(token, 10L, change).get(AjaxResult.DATA_TAG));
- assertSame(detail, controller.updateAddress(token, confirmation).get(AjaxResult.DATA_TAG));
- assertSame(detail, controller.addTip(token, tip).get(AjaxResult.DATA_TAG));
- }
- @Test
- void rateEndpointDelegatesSenderAndStarsToService() {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- var request = new com.ruoyi.app.flashdelivery.dto.FlashDeliveryRatingRequest();
- request.setOrderId(10L);
- request.setStars(4.5);
- new FlashDeliveryUserController(service).rate(JwtUtil.token("7", "user"), request);
- verify(service).rateRider(7L, 10L, request);
- }
- @Test
- void detailByOrderNoEndpointsDelegateToService() {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- FlashDeliveryOrderDetailView detail = new FlashDeliveryOrderDetailView();
- when(service.userDetailByOrderNo(7L, "FL-1")).thenReturn(detail);
- when(service.riderDetailByOrderNo(8L, "FL-1")).thenReturn(detail);
- AjaxResult userResult = new FlashDeliveryUserController(service)
- .detailByOrderNo(JwtUtil.token("7", "user"), "FL-1");
- AjaxResult riderResult = new FlashDeliveryRiderController(service)
- .detailByOrderNo(JwtUtil.token("8", "rider"), "FL-1");
- assertSame(detail, userResult.get(AjaxResult.DATA_TAG));
- assertSame(detail, riderResult.get(AjaxResult.DATA_TAG));
- }
- @Test
- void addressConfirmationReturnsLatestQuoteForAnotherUserConfirmation() {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- var input = new com.ruoyi.app.flashdelivery.dto.FlashDeliveryAddressConfirmRequest();
- input.setOrderId(10L);
- FlashDeliveryQuoteView latest = new FlashDeliveryQuoteView();
- latest.setOrderVersion(2);
- latest.setAmount(123L);
- when(service.updateAddress(7L, 10L, input)).thenThrow(new FlashDeliveryQuoteChangedException(latest));
- AjaxResult result = new FlashDeliveryUserController(service)
- .updateAddress(JwtUtil.token("7", "user"), input);
- assertSame(latest, result.get(AjaxResult.DATA_TAG));
- assertTrue(((Number) result.get(AjaxResult.CODE_TAG)).intValue() != 200);
- }
- @Test
- void createReturnsLatestQuoteWhenClientQuoteChanged() {
- FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
- FlashDeliveryCreateRequest request = new FlashDeliveryCreateRequest();
- FlashDeliveryQuoteView latest = new FlashDeliveryQuoteView();
- latest.setAmount(120L);
- when(service.create(7L, request)).thenThrow(new FlashDeliveryQuoteChangedException(latest));
- AjaxResult result = new FlashDeliveryUserController(service)
- .create(JwtUtil.token("7", "user"), request);
- assertSame(latest, result.get(AjaxResult.DATA_TAG));
- assertTrue(((Number) result.get(AjaxResult.CODE_TAG)).intValue() != 200);
- }
- @Test
- void everyAdminEndpointDeclaresPlatformPermission() {
- for (Method method : FlashDeliveryAdminController.class.getDeclaredMethods()) {
- if (method.isSynthetic()) continue;
- assertNotNull(method.getAnnotation(PreAuthorize.class), method.getName());
- assertTrue(method.getAnnotation(PreAuthorize.class).value().contains("flash:"));
- }
- }
- @Test
- void pricingAndOrderInterventionsAreOperationAudited() throws Exception {
- assertNotNull(FlashDeliveryAdminController.class.getMethod("createPricing",
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryPricingRequest.class).getAnnotation(Log.class));
- assertNotNull(FlashDeliveryAdminController.class.getMethod("updatePricing", Long.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryPricingRequest.class).getAnnotation(Log.class));
- assertNotNull(FlashDeliveryAdminController.class.getMethod("deletePricing", Long.class).getAnnotation(Log.class));
- assertNotNull(FlashDeliveryAdminController.class.getMethod("cancel", Long.class,
- com.ruoyi.app.flashdelivery.dto.FlashDeliveryReasonRequest.class).getAnnotation(Log.class));
- assertNotNull(FlashDeliveryAdminController.class.getMethod("complete", Long.class).getAnnotation(Log.class));
- }
- @Test
- void everyAppEndpointDeclaresMethodLevelTokenAuthentication() {
- for (Class<?> controller : new Class<?>[]{FlashDeliveryUserController.class,
- FlashDeliveryRiderController.class}) {
- for (Method method : controller.getDeclaredMethods()) {
- if (!java.lang.reflect.Modifier.isPublic(method.getModifiers())) continue;
- assertNotNull(method.getAnnotation(Auth.class), controller.getSimpleName() + "." + method.getName());
- }
- }
- }
- }
|