产品明细单元测试完善

This commit is contained in:
gaoqr
2025-10-20 18:07:30 +08:00
parent 25b26c83dd
commit a3633fc6ef
7 changed files with 345 additions and 128 deletions
@@ -0,0 +1,294 @@
package com.cf.imes.module.system.service.funds.products;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
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.ProductDetailsSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsDetailMapper;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper;
import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum;
import com.cf.imes.module.system.enums.products.ProductStatusEnum;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.math.BigDecimal;
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_DETAIL_DURATION_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_DETAIL_NO_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_DETAIL_NO_UPDATE;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_NOT_NOLIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_NO_EXIST;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
/**
* @author Gqr
* @since 2025/10/14 13:48
*/
@Import(ProductsDetailServiceImpl.class)
public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
private ProductsDetailServiceImpl productsDetailService;
@Resource
private ProductsDetailMapper productsDetailMapper;
@MockitoBean
private ProductsMapper productsMapper;
@Test
void testCreateProductDetails() {
// mock下架状态的产品
ProductsDO mockProduct = new ProductsDO();
mockProduct.setId(123L);
mockProduct.setDeleted(false);
mockProduct.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus());
when(productsMapper.selectOne(any())).thenReturn(mockProduct);
ProductDetailsSaveReqVO productDetailsSaveReqVO = randomPojo(ProductDetailsSaveReqVO.class, p -> {
p.setId(null);
});
// 调用
Long id = productsDetailService.create(productDetailsSaveReqVO);
// 断言
assertNotNull(id);
// 校验记录的属性是否正确
ProductsDetailDO productsDetailDO = productsDetailMapper.selectById(id);
assertPojoEquals(productDetailsSaveReqVO, productsDetailDO, "id");
}
@Test
void testCreateProductDetails_ProductNotExist() {
ProductDetailsSaveReqVO productDetailsSaveReqVO = randomPojo(ProductDetailsSaveReqVO.class);
when(productsMapper.selectOne(any())).thenReturn(null);
assertServiceException(() -> productsDetailService.create(productDetailsSaveReqVO),
PRODUCTS_NO_EXIST);
ProductsDO mockProduct = new ProductsDO();
mockProduct.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus());
when(productsMapper.selectOne(any())).thenReturn(mockProduct);
assertServiceException(() -> productsDetailService.create(productDetailsSaveReqVO),
PRODUCTS_DETAIL_NO_UPDATE);
}
@Test
void testCheckProductDetails_duplicate() {
// mock下架状态的产品
ProductsDO mockProduct = new ProductsDO();
mockProduct.setId(123L);
mockProduct.setDeleted(false);
mockProduct.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus());
when(productsMapper.selectOne(any())).thenReturn(mockProduct);
// 插入一条与 createReqVO 冲突的数据
ProductsDetailDO existing = new ProductsDetailDO();
existing.setProductId(1L);
existing.setDuration(12);
existing.setDurationUnit(0);
existing.setDeleted(false);
productsDetailMapper.insert(existing);
// 模拟新增同样 duration + unit 的记录
ProductDetailsSaveReqVO reqVO = new ProductDetailsSaveReqVO()
.setProductId(existing.getProductId())
.setDuration(existing.getDuration())
.setDurationUnit(existing.getDurationUnit());
assertServiceException(() -> productsDetailService.create(reqVO),
PRODUCTS_DETAIL_DURATION_EXIST, reqVO.getDuration(), ProductDurationUnitEnum.getDesc(reqVO.getDurationUnit()));
}
@Test
void updateProductDetails() {
// mock下架状态的产品
ProductsDO mockProduct = new ProductsDO();
mockProduct.setId(123L);
mockProduct.setDeleted(false);
mockProduct.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus());
when(productsMapper.selectOne(any())).thenReturn(mockProduct);
ProductsDetailDO detail = new ProductsDetailDO();
detail.setProductId(mockProduct.getId());
detail.setDuration(12);
detail.setDurationUnit(1);
detail.setDeleted(false);
productsDetailMapper.insert(detail);
// 构造请求
ProductDetailsSaveReqVO reqVO = new ProductDetailsSaveReqVO()
.setId(detail.getId())
.setProductId(mockProduct.getId())
.setDuration(6)
.setDurationUnit(0);
// 调用
productsDetailService.update(reqVO);
// 验证结果
ProductsDetailDO updated = productsDetailMapper.selectById(detail.getId());
assertEquals(6, updated.getDuration());
}
@Test
void deleteTest(){
// mock下架状态的产品
ProductsDO mockProduct = new ProductsDO();
mockProduct.setId(123L);
mockProduct.setDeleted(false);
mockProduct.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus());
when(productsMapper.selectOne(any())).thenReturn(mockProduct);
ProductsDetailDO detail = new ProductsDetailDO();
detail.setProductId(mockProduct.getId());
detail.setDuration(12);
detail.setDurationUnit(1);
detail.setDeleted(false);
productsDetailMapper.insert(detail);
// 调用删除
productsDetailService.delete(detail.getId());
// 验证确实被删
assertNull(productsDetailMapper.selectById(detail.getId()));
}
@Test
void testGet_success() {
// 插入一条数据
ProductsDetailDO detail = new ProductsDetailDO();
detail.setId(321L);
detail.setDeleted(false);
detail.setProductId(123L);
productsDetailMapper.insert(detail);
ProductsDetailDO result = productsDetailService.get(detail.getId());
assertNotNull(result);
assertEquals(321L, result.getId());
assertEquals(123L, result.getProductId());
}
@Test
void testGetPage_success() {
ProductsDetailDO detail = randomPojo(ProductsDetailDO.class, o -> {
o.setProductId(123L);
o.setDuration(1);
o.setDurationUnit(ProductDurationUnitEnum.YEAR.getCode());
o.setDiscount(BigDecimal.valueOf(100));
o.setDeleted(false);
});
productsDetailMapper.insert(detail);
// 不匹配 productId
productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setProductId(321L)));
// 不匹配 duration
productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setDuration(2)));
// 不匹配 discount
productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setDiscount(BigDecimal.valueOf(99))));
// 被逻辑删除
productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setDeleted(true)));
// ============ 构造查询参数 ============
ProductDetailsPageReqVO reqVO = new ProductDetailsPageReqVO();
reqVO.setProductId(123L);
reqVO.setDuration(1);
reqVO.setDiscount(BigDecimal.valueOf(100));
reqVO.setPageNo(1);
reqVO.setPageSize(10);
// ============ 调用方法 ============
PageResult<ProductsDetailDO> pageResult = productsDetailService.getPage(reqVO);
// ============ 断言结果 ============
assertEquals(1, pageResult.getTotal(), "分页结果数量应为1");
assertEquals(1, pageResult.getList().size(), "分页列表长度应为1");
assertPojoEquals(detail, pageResult.getList().get(0));
}
@Test
void validateProductDetailsExists_idNull(){
assertServiceException(() -> productsDetailService.validateProductDetailsExists(null), PRODUCTS_DETAIL_NO_EXIST);
}
@Test
void validateProductDetailsExists_notExist(){
assertServiceException(() -> productsDetailService.validateProductDetailsExists(1234567L), PRODUCTS_DETAIL_NO_EXIST);
}
@Test
void testValidateProductExist_success() {
// 模拟返回一个正常的产品
ProductsDO product = new ProductsDO();
product.setId(1L);
product.setDeleted(false);
product.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus());
when(productsMapper.selectOne(any())).thenReturn(product);
ProductsDO result = productsDetailService.validateProductExist(1L);
assertNotNull(result);
assertEquals(1L, result.getId());
}
@Test
void testValidateProductExist_notExist() {
// 模拟数据库返回 null
when(productsMapper.selectOne(any())).thenReturn(null);
assertServiceException(() -> productsDetailService.validateProductExist(1L), PRODUCTS_NO_EXIST);
}
@Test
void testValidateProductExist_statusNotUp() {
ProductsDO product = new ProductsDO();
product.setId(1L);
product.setDeleted(false);
product.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); // 非 PRODUCT_UPDATES 状态
when(productsMapper.selectOne(any())).thenReturn(product);
assertServiceException(() -> productsDetailService.validateProductExist(1L), PRODUCTS_NOT_NOLIST);
}
@Test
void testGetProductDetailOneYearDiscount_exists() {
// 模拟数据库返回一年期明细
ProductsDetailDO detailDO = new ProductsDetailDO();
detailDO.setProductId(1L);
detailDO.setDuration(1);
detailDO.setDurationUnit(ProductDurationUnitEnum.YEAR.getCode());
detailDO.setDiscount(BigDecimal.valueOf(85));
productsDetailMapper.insert(detailDO);
BigDecimal discount = productsDetailService.getProductDetailOneYearDiscount(1L);
assertEquals(BigDecimal.valueOf(85), discount);
}
@Test
void testGetProductDetailOneYearDiscount_notExist() {
BigDecimal discount = productsDetailService.getProductDetailOneYearDiscount(123L);
assertEquals(BigDecimal.valueOf(100), discount);
}
}
@@ -686,16 +686,30 @@ CREATE TABLE IF NOT EXISTS "process_group" (
) COMMENT '工序组表 process_group';
CREATE TABLE IF NOT EXISTS "products" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"product_name" varchar(64) NOT NULL,
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"product_name" varchar(64) NOT NULL,
"status" tinyint DEFAULT 1 NOT NULL,
"software_id" bigint NOT NULL,
"price" decimal(8,2),
"description" varchar,
"creator" varchar DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '产品表';
CREATE TABLE IF NOT EXISTS "products_details" (
"id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"product_id" BIGINT NOT NULL,
"duration" VARCHAR,
"duration_unit" TINYINT,
"discount" DECIMAL(3),
"creator" VARCHAR DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '产品购买信息表 products_details';