From 920ffe3cf5fd867399845c9a5798f80af446de68 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Fri, 24 Oct 2025 10:44:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=98=8E=E7=BB=86=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=E5=AE=8C=E5=96=84=E3=80=81=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E5=AD=97=E6=AE=B5=E7=A7=BB=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../productDetails/ProductDetailsRespVO.java | 20 --- .../ProductDetailsSaveReqVO.java | 7 - .../ProductsDetailControllerTest.java | 168 ++++++++++++++++++ 3 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailControllerTest.java diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java index 00369f3d4..d94e6c739 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java @@ -1,7 +1,6 @@ package com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.cf.imes.module.system.validation.products.ProductType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -20,28 +19,12 @@ public class ProductDetailsRespVO { @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long productId; - @Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买方式:0时长;1产量") - @ProductType - private Integer purchaseType; - @Schema(description = "购买时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer duration; @Schema(description = "产品时长单位,0:年、1:月", example = "1") private Integer durationUnit; - @Schema(description = "正常产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") - private BigDecimal output; - - @Schema(description = "赠送时长", example = "1") - private Integer giftDuration; - - @Schema(description = "赠送时长单位,0:年、1:月", example = "1") - private Integer giftDurationUnit; - - @Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") - private BigDecimal giftOutput; - @Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private BigDecimal originalPrice; @@ -51,9 +34,6 @@ public class ProductDetailsRespVO { @Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") private BigDecimal currentPrice; - @Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "是") - private Boolean isDiscounted; - @Schema(description = "操作时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime updateTime; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java index 652cd289a..5cee0af91 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java @@ -1,6 +1,5 @@ package com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails; -import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum; import com.cf.imes.module.system.validation.products.ProductDurationUnitValid; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.DecimalMax; @@ -23,9 +22,6 @@ public class ProductDetailsSaveReqVO { @NotNull(message = "产品名称不能为空") private Long productId; - @Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - private Integer purchaseType = ProductsPurchaseTypeEnum.DURATION.getStatus(); - @Schema(description = "产品时长,格式:时长值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Min(value = 1, message = "产品时长必须大于0") @NotNull(message = "产品时长不能为空") @@ -43,7 +39,4 @@ public class ProductDetailsSaveReqVO { @NotNull(message = "折扣不能为空") private BigDecimal discount; - @Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean isDiscounted; - } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailControllerTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailControllerTest.java new file mode 100644 index 000000000..9814d0837 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailControllerTest.java @@ -0,0 +1,168 @@ +package com.cf.imes.module.system.controller.admin.funds.products; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsRespVO; +import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; +import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum; +import com.cf.imes.module.system.service.funds.products.ProductsDetailService; +import com.cf.imes.module.system.service.funds.purchase.PurchaseService; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.math.BigDecimal; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Gqr + * @since 2025/10/24 9:41 + */ +@WebMvcTest(controllers = ProductsDetailController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class) +public class ProductsDetailControllerTest { + @Autowired + private MockMvc mockMvc; + + @MockitoBean + private ProductsDetailService productsDetailService; + + @MockitoBean + private PurchaseService purchaseService; + + @Autowired + private ObjectMapper objectMapper; + + @Test + void testCreateProductDetails() throws Exception { + ProductDetailsSaveReqVO vo = new ProductDetailsSaveReqVO(); + vo.setProductId(123L); + vo.setDuration(1); + vo.setDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); + vo.setDiscount(BigDecimal.valueOf(100)); + + // mock Service 返回 + when(productsDetailService.create(any())).thenReturn(100L); + + mockMvc.perform(put("/system/product-details") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(vo))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data").value(100)); + + // 验证 Service 调用 + verify(productsDetailService, times(1)).create(any()); + } + + @Test + void testUpdateProductDetails() throws Exception { + ProductDetailsSaveReqVO vo = new ProductDetailsSaveReqVO(); + vo.setId(1L); + vo.setProductId(123L); + vo.setDuration(2); + vo.setDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); + vo.setDiscount(BigDecimal.valueOf(80)); + + // mock Service 方法 void 不做实际处理 + doNothing().when(productsDetailService).update(any()); + + mockMvc.perform(post("/system/product-details") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(vo))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data").value(true)); + + verify(productsDetailService, times(1)).update(any()); + } + + @Test + void testDeleteProductDetails() throws Exception { + Long id = 3L; + doNothing().when(productsDetailService).delete(anyLong()); + + mockMvc.perform(delete("/system/product-details") + .param("id", id.toString())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data").value(true)); + + verify(productsDetailService, times(1)).delete(id); + } + + @Test + void testGetProducts() throws Exception { + Long id = 4L; + ProductsDetailDO mockProduct = new ProductsDetailDO() + .setId(id) + .setProductId(123L); + when(productsDetailService.get(id)).thenReturn(mockProduct); + + mockMvc.perform(get("/system/product-details/{id}", id)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data.productId").value(123L)); + + verify(productsDetailService, times(1)).get(id); + } + + @Test + void testGetProductsPage() throws Exception { + ProductDetailsPageReqVO reqVO = new ProductDetailsPageReqVO(); + PageResult mockPage = new PageResult<>(); + mockPage.setTotal(1L); + mockPage.setList(List.of(new ProductsDetailDO().setId(1L).setProductId(123L))); + when(productsDetailService.getPage(any())).thenReturn(mockPage); + + mockMvc.perform(get("/system/product-details/page") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(reqVO))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data.list[0].productId").value(123L)); + + verify(productsDetailService, times(1)).getPage(any()); + } + + + @Test + void testGetOrgProductDetailList() throws Exception { + // 模拟返回数据 + ProductDetailsRespVO mockVO = new ProductDetailsRespVO(); + mockVO.setId(1L); + mockVO.setProductId(1001L); + List mockList = List.of(mockVO); + + // Mock Service 层行为 + when(purchaseService.getOrgProductDetailList(anyLong(), anyLong())) + .thenReturn(mockList); + + // 执行请求 + mockMvc.perform(get("/system/product-details/organ/purchase") + .param("organId", "100") + .param("productId", "200") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data[0].productId").value(1001)) + .andExpect(jsonPath("$.data[0].id").value(1L)); + + // 验证 Service 是否被正确调用一次 + verify(purchaseService, times(1)).getOrgProductDetailList(100L, 200L); + } + +}