产品明细单元测试完善、无用字段移除

This commit is contained in:
gaoqr
2025-10-24 10:44:07 +08:00
parent e5b4a7b6ce
commit 920ffe3cf5
3 changed files with 168 additions and 27 deletions
@@ -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;
@@ -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;
}
@@ -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<ProductsDetailDO> 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<ProductDetailsRespVO> 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);
}
}