diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
index 19a83b2..36ae95f 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
@@ -118,6 +118,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
if (crmProductService.getProductByCategoryId(id) > 0) {
throw exception(PRODUCT_CATEGORY_USED);
}
+
// 2. 删除
productCategoryMapper.deleteById(id);
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
index 785fa22..ce88f2a 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
@@ -135,9 +135,9 @@ public class CrmProductServiceImpl implements CrmProductService {
success = CRM_PRODUCT_DELETE_SUCCESS)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
public void deleteProduct(Long id) {
- // 校验存在
+ // 1.1 校验存在
CrmProductDO product = validateProductExists(id);
- // 校验未被合同/商机引用,避免删除后产生悬空引用
+ // 1.2 校验未被合同/商机引用,避免删除后产生悬空引用
if (contractService.getContractProductCountByProductId(id) > 0) {
throw exception(PRODUCT_DELETE_FAIL_CONTRACT_EXISTS);
}
@@ -145,10 +145,10 @@ public class CrmProductServiceImpl implements CrmProductService {
throw exception(PRODUCT_DELETE_FAIL_BUSINESS_EXISTS);
}
- // 删除
+ // 2. 删除
productMapper.deleteById(id);
- // 记录操作日志上下文
+ // 3. 记录操作日志上下文
LogRecordContext.putVariable("product", product);
}
diff --git a/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImplTest.java b/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImplTest.java
new file mode 100644
index 0000000..88d5e8b
--- /dev/null
+++ b/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImplTest.java
@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.module.crm.service.product;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
+import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductCategoryMapper;
+import com.mzt.logapi.context.LogRecordContext;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link CrmProductCategoryServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+public class CrmProductCategoryServiceImplTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private CrmProductCategoryServiceImpl productCategoryService;
+
+ @Mock
+ private CrmProductCategoryMapper productCategoryMapper;
+ @Mock
+ private CrmProductService crmProductService;
+
+ @BeforeEach
+ public void setUp() {
+ LogRecordContext.putEmptySpan();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ LogRecordContext.clear();
+ }
+
+ @Test
+ public void testDeleteProductCategory_success() {
+ // mock 数据
+ CrmProductCategoryDO category = new CrmProductCategoryDO().setId(1L).setName("芋道分类").setParentId(0L);
+ when(productCategoryMapper.selectById(1L)).thenReturn(category);
+ // mock 方法(无子分类、未被产品使用)
+ when(productCategoryMapper.selectCountByParentId(1L)).thenReturn(0L);
+ when(crmProductService.getProductByCategoryId(1L)).thenReturn(0L);
+
+ // 调用
+ productCategoryService.deleteProductCategory(1L);
+ // 断言
+ verify(productCategoryMapper).deleteById(1L);
+ // 断言操作日志上下文,为删除前的分类
+ CrmProductCategoryDO logCategory = (CrmProductCategoryDO) LogRecordContext.getVariable("productCategory");
+ assertSame(category, logCategory);
+ assertEquals("芋道分类", logCategory.getName());
+ }
+
+ @Test
+ public void testDeleteProductCategory_notExists() {
+ // 调用,并断言异常
+ assertServiceException(() -> productCategoryService.deleteProductCategory(1L), PRODUCT_CATEGORY_NOT_EXISTS);
+ // 断言
+ verify(productCategoryMapper, never()).deleteById(anyLong());
+ assertNull(LogRecordContext.getVariable("productCategory"));
+ }
+
+ @Test
+ public void testDeleteProductCategory_existsChildren() {
+ // mock 数据
+ when(productCategoryMapper.selectById(1L)).thenReturn(new CrmProductCategoryDO().setId(1L).setName("芋道分类"));
+ // mock 方法(存在子分类)
+ when(productCategoryMapper.selectCountByParentId(1L)).thenReturn(1L);
+
+ // 调用,并断言异常
+ assertServiceException(() -> productCategoryService.deleteProductCategory(1L), PRODUCT_CATEGORY_EXISTS_CHILDREN);
+ // 断言
+ verify(productCategoryMapper, never()).deleteById(anyLong());
+ verifyNoInteractions(crmProductService);
+ assertNull(LogRecordContext.getVariable("productCategory"));
+ }
+
+ @Test
+ public void testDeleteProductCategory_used() {
+ // mock 数据
+ when(productCategoryMapper.selectById(1L)).thenReturn(new CrmProductCategoryDO().setId(1L).setName("芋道分类"));
+ // mock 方法(被产品使用)
+ when(productCategoryMapper.selectCountByParentId(1L)).thenReturn(0L);
+ when(crmProductService.getProductByCategoryId(1L)).thenReturn(1L);
+
+ // 调用,并断言异常
+ assertServiceException(() -> productCategoryService.deleteProductCategory(1L), PRODUCT_CATEGORY_USED);
+ // 断言
+ verify(productCategoryMapper, never()).deleteById(anyLong());
+ assertNull(LogRecordContext.getVariable("productCategory"));
+ }
+
+}
diff --git a/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImplTest.java b/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImplTest.java
new file mode 100644
index 0000000..551deb0
--- /dev/null
+++ b/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImplTest.java
@@ -0,0 +1,113 @@
+package cn.iocoder.yudao.module.crm.service.product;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
+import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductMapper;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
+import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
+import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import com.mzt.logapi.context.LogRecordContext;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link CrmProductServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+public class CrmProductServiceImplTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private CrmProductServiceImpl productService;
+
+ @Mock
+ private CrmProductMapper productMapper;
+ @Mock
+ private CrmProductCategoryService productCategoryService;
+ @Mock
+ private CrmContractService contractService;
+ @Mock
+ private CrmBusinessService businessService;
+ @Mock
+ private CrmPermissionService permissionService;
+ @Mock
+ private AdminUserApi adminUserApi;
+
+ @BeforeEach
+ public void setUp() {
+ LogRecordContext.putEmptySpan();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ LogRecordContext.clear();
+ }
+
+ @Test
+ public void testDeleteProduct_success() {
+ // mock 数据
+ CrmProductDO product = new CrmProductDO().setId(1L).setName("芋道产品");
+ when(productMapper.selectById(1L)).thenReturn(product);
+ // mock 方法(未被合同、商机引用)
+ when(contractService.getContractProductCountByProductId(1L)).thenReturn(0L);
+ when(businessService.getBusinessProductCountByProductId(1L)).thenReturn(0L);
+
+ // 调用
+ productService.deleteProduct(1L);
+ // 断言
+ verify(productMapper).deleteById(1L);
+ // 断言操作日志上下文,为删除前的产品
+ CrmProductDO logProduct = (CrmProductDO) LogRecordContext.getVariable("product");
+ assertSame(product, logProduct);
+ assertEquals("芋道产品", logProduct.getName());
+ }
+
+ @Test
+ public void testDeleteProduct_notExists() {
+ // 调用,并断言异常
+ assertServiceException(() -> productService.deleteProduct(1L), PRODUCT_NOT_EXISTS);
+ // 断言
+ verify(productMapper, never()).deleteById(anyLong());
+ assertNull(LogRecordContext.getVariable("product"));
+ }
+
+ @Test
+ public void testDeleteProduct_contractExists() {
+ // mock 数据
+ when(productMapper.selectById(1L)).thenReturn(new CrmProductDO().setId(1L).setName("芋道产品"));
+ // mock 方法(被合同引用)
+ when(contractService.getContractProductCountByProductId(1L)).thenReturn(1L);
+
+ // 调用,并断言异常
+ assertServiceException(() -> productService.deleteProduct(1L), PRODUCT_DELETE_FAIL_CONTRACT_EXISTS);
+ // 断言
+ verify(productMapper, never()).deleteById(anyLong());
+ assertNull(LogRecordContext.getVariable("product"));
+ }
+
+ @Test
+ public void testDeleteProduct_businessExists() {
+ // mock 数据
+ when(productMapper.selectById(1L)).thenReturn(new CrmProductDO().setId(1L).setName("芋道产品"));
+ // mock 方法(被商机引用)
+ when(contractService.getContractProductCountByProductId(1L)).thenReturn(0L);
+ when(businessService.getBusinessProductCountByProductId(1L)).thenReturn(1L);
+
+ // 调用,并断言异常
+ assertServiceException(() -> productService.deleteProduct(1L), PRODUCT_DELETE_FAIL_BUSINESS_EXISTS);
+ // 断言
+ verify(productMapper, never()).deleteById(anyLong());
+ assertNull(LogRecordContext.getVariable("product"));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product/pom.xml b/yudao-module-mall/yudao-module-product/pom.xml
index d6377bc..96131bf 100644
--- a/yudao-module-mall/yudao-module-product/pom.xml
+++ b/yudao-module-mall/yudao-module-product/pom.xml
@@ -24,7 +24,7 @@
${revision}
-
+
cn.iocoder.boot
yudao-module-trade-api
diff --git a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
index e2056fd..0d69c55 100755
--- a/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.product.service.spu;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
-import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
@@ -17,29 +17,37 @@ import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceIm
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl;
+import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_RECYCLE;
+import static java.util.Collections.singletonList;
import static org.assertj.core.util.Lists.newArrayList;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
// TODO @芋艿:review 下单元测试
@@ -48,10 +56,12 @@ import static org.mockito.Mockito.when;
*
* @author 芋道源码
*/
-@Disabled // TODO 芋艿:后续 fix 补充的单测
+// DONE 芋艿:后续 fix 补充的单测
@Import(ProductSpuServiceImpl.class)
public class ProductSpuServiceImplTest extends BaseDbUnitTest {
+ private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
+
@Resource
private ProductSpuServiceImpl productSpuService;
@@ -84,18 +94,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
public void testCreateSpu_success() {
// 准备参数
- ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{
- // 限制范围为正整数
- o.setCostPrice(generaInt());
- o.setPrice(generaInt());
- o.setMarketPrice(generaInt());
- o.setStock(generaInt());
- o.setFirstBrokeragePrice(generaInt());
- o.setSecondBrokeragePrice(generaInt());
- // 限制分数为两位数
- o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
- o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
- });
+ ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomSkuSaveReqVO();
ProductSpuSaveReqVO createReqVO = randomPojo(ProductSpuSaveReqVO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
@@ -104,291 +103,215 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO));
});
+ // mock 方法(分类层级)
when(categoryService.getCategoryLevel(eq(createReqVO.getCategoryId()))).thenReturn(2);
- Long spu = productSpuService.createSpu(createReqVO);
- ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
- assertPojoEquals(createReqVO, productSpuDO);
+
+ // 调用
+ Long spuId = productSpuService.createSpu(createReqVO);
+ // 断言:销量、浏览量为初始值
+ ProductSpuDO productSpuDO = productSpuMapper.selectById(spuId);
+ assertPojoEquals(createReqVO, productSpuDO, "salesCount", "browseCount");
+ assertEquals(ProductSpuStatusEnum.ENABLE.getStatus(), productSpuDO.getStatus());
+ assertEquals(0, productSpuDO.getSalesCount());
+ assertEquals(0, productSpuDO.getBrowseCount());
+ // 断言:基于 SKU 初始化价格、库存
+ assertEquals(skuCreateOrUpdateReqVO.getPrice(), productSpuDO.getPrice());
+ assertEquals(skuCreateOrUpdateReqVO.getMarketPrice(), productSpuDO.getMarketPrice());
+ assertEquals(skuCreateOrUpdateReqVO.getCostPrice(), productSpuDO.getCostPrice());
+ assertEquals(skuCreateOrUpdateReqVO.getStock() * 3, productSpuDO.getStock());
+ // 断言:创建 SKU
+ verify(productSkuService).createSkuList(eq(spuId), eq(createReqVO.getSkus()));
}
@Test
public void testUpdateSpu_success() {
+ // mock 数据
+ ProductSpuDO dbSpu = randomSpuDO();
+ productSpuMapper.insert(dbSpu);
// 准备参数
- ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(generaInt()); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- });
- productSpuMapper.insert(createReqVO);
- // 准备参数
- ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{
- // 限制范围为正整数
- o.setCostPrice(generaInt());
- o.setPrice(generaInt());
- o.setMarketPrice(generaInt());
- o.setStock(generaInt());
- o.setFirstBrokeragePrice(generaInt());
- o.setSecondBrokeragePrice(generaInt());
- // 限制分数为两位数
- o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
- o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
- });
- // 准备参数
+ ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomSkuSaveReqVO();
ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class, o -> {
- o.setId(createReqVO.getId()); // 设置更新的 ID
+ o.setId(dbSpu.getId()); // 设置更新的 ID
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO));
});
+ // mock 方法(分类层级)
when(categoryService.getCategoryLevel(eq(reqVO.getCategoryId()))).thenReturn(2);
+
// 调用
productSpuService.updateSpu(reqVO);
- // 校验是否更新正确
+ // 校验是否更新正确:状态保持不变
ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, spu);
+ assertEquals(dbSpu.getStatus(), spu.getStatus());
+ assertEquals(skuCreateOrUpdateReqVO.getStock() * 3, spu.getStock());
+ // 断言:更新 SKU
+ verify(productSkuService).updateSkuList(eq(reqVO.getId()), eq(reqVO.getSkus()));
}
@Test
- public void testValidateSpuExists_exception() {
+ public void testUpdateSpu_notExists() {
+ // 准备参数
ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class);
- // 调用
- Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO));
+
+ // 调用, 并断言异常
+ assertServiceException(() -> productSpuService.updateSpu(reqVO), SPU_NOT_EXISTS);
}
@Test
- void deleteSpu() {
- // 准备参数
- ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(generaInt()); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- o.setStatus(-1); // 加入回收站才可删除
- });
- productSpuMapper.insert(createReqVO);
+ public void testValidateDeliveryTypes_success() {
+ // 调用,并断言:快递发货、用户自提,及其组合
+ assertEquals(Collections.emptySet(), validateDeliveryTypes(singletonList(DeliveryTypeEnum.EXPRESS.getType())));
+ assertEquals(Collections.emptySet(), validateDeliveryTypes(singletonList(DeliveryTypeEnum.PICK_UP.getType())));
+ assertEquals(Collections.emptySet(), validateDeliveryTypes(Arrays.asList(
+ DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.PICK_UP.getType())));
+ }
+
+ @Test
+ public void testValidateDeliveryTypes_invalid() {
+ // 调用,并断言:不在枚举范围内
+ Set invalidMessages = Collections.singleton("配送方式不正确");
+ assertEquals(invalidMessages, validateDeliveryTypes(singletonList(0)));
+ assertEquals(invalidMessages, validateDeliveryTypes(singletonList(3)));
+ assertEquals(invalidMessages, validateDeliveryTypes(singletonList(-1)));
+ assertEquals(invalidMessages, validateDeliveryTypes(Arrays.asList(DeliveryTypeEnum.EXPRESS.getType(), 3)));
+ assertEquals(invalidMessages, validateDeliveryTypes(Arrays.asList(DeliveryTypeEnum.EXPRESS.getType(), null)));
+ // 调用,并断言:为空
+ Set emptyMessages = Collections.singleton("配送方式不能为空");
+ assertEquals(emptyMessages, validateDeliveryTypes(null));
+ assertEquals(emptyMessages, validateDeliveryTypes(Collections.emptyList()));
+ }
+
+ @Test
+ public void testDeleteSpu_success() {
+ // mock 数据
+ ProductSpuDO dbSpu = randomSpuDO(o -> o.setStatus(ProductSpuStatusEnum.RECYCLE.getStatus())); // 加入回收站才可删除
+ productSpuMapper.insert(dbSpu);
// 调用
- productSpuService.deleteSpu(createReqVO.getId());
+ productSpuService.deleteSpu(dbSpu.getId());
+ // 断言
+ assertNull(productSpuMapper.selectById(dbSpu.getId()));
+ verify(productSkuService).deleteSkuBySpuId(eq(dbSpu.getId()));
+ }
+
+ @Test
+ public void testDeleteSpu_notRecycle() {
+ // mock 数据
+ ProductSpuDO dbSpu = randomSpuDO(o -> o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus()));
+ productSpuMapper.insert(dbSpu);
- Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId()));
+ // 调用, 并断言异常
+ assertServiceException(() -> productSpuService.deleteSpu(dbSpu.getId()), SPU_NOT_RECYCLE);
+ // 断言
+ assertNotNull(productSpuMapper.selectById(dbSpu.getId()));
+ verify(productSkuService, never()).deleteSkuBySpuId(any());
}
@Test
- void getSpu() {
- // 准备参数
- ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(generaInt()); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- });
- productSpuMapper.insert(createReqVO);
+ public void testGetSpu() {
+ // mock 数据
+ ProductSpuDO dbSpu = randomSpuDO();
+ productSpuMapper.insert(dbSpu);
- ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId());
- assertPojoEquals(createReqVO, spu);
+ // 调用
+ ProductSpuDO spu = productSpuService.getSpu(dbSpu.getId());
+ // 断言
+ assertPojoEquals(dbSpu, spu);
}
@Test
- void getSpuList() {
- // 准备参数
- ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(generaInt()); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- }), randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(generaInt()); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- }));
- productSpuMapper.insertBatch(createReqVOs);
+ public void testGetSpuList() {
+ // mock 数据
+ ArrayList dbSpus = Lists.newArrayList(randomSpuDO(), randomSpuDO());
+ productSpuMapper.insertBatch(dbSpus);
+ // 准备参数:倒序传入
+ List ids = Arrays.asList(dbSpus.get(1).getId(), dbSpus.get(0).getId());
// 调用
- List spuList = productSpuService.getSpuList(createReqVOs.stream().map(ProductSpuDO::getId).collect(Collectors.toList()));
- Assertions.assertIterableEquals(createReqVOs, spuList);
+ List spuList = productSpuService.getSpuList(ids);
+ // 断言:按照 ids 顺序返回
+ assertEquals(ids, convertList(spuList, ProductSpuDO::getId));
+ assertPojoEquals(dbSpus.get(1), spuList.get(0));
+ assertPojoEquals(dbSpus.get(0), spuList.get(1));
}
@Test
- void getSpuPage_alarmStock_empty() {
+ public void testGetSpuPage_alertStockEmpty() {
+ // mock 数据
+ ArrayList dbSpus = Lists.newArrayList(randomSpuDO(o -> o.setStock(11)),
+ randomSpuDO(o -> o.setStock(11)));
+ productSpuMapper.insertBatch(dbSpus);
// 准备参数
- ArrayList createReqVOs = Lists.newArrayList(randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(11); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- }), randomPojo(ProductSpuDO.class,o->{
- o.setCategoryId(generateId());
- o.setBrandId(generateId());
- o.setDeliveryTemplateId(generateId());
- o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setVirtualSalesCount(generaInt()); // 限制范围为正整数
- o.setPrice(generaInt()); // 限制范围为正整数
- o.setMarketPrice(generaInt()); // 限制范围为正整数
- o.setCostPrice(generaInt()); // 限制范围为正整数
- o.setStock(11); // 限制范围为正整数
- o.setGiveIntegral(generaInt()); // 限制范围为正整数
- o.setSalesCount(generaInt()); // 限制范围为正整数
- o.setBrowseCount(generaInt()); // 限制范围为正整数
- }));
- productSpuMapper.insertBatch(createReqVOs);
- // 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK);
+ // 调用
PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
-
- PageResult