diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 91567bd..f42b44b 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -188,9 +188,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @Transactional(rollbackFor = Exception.class) public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId); - if (product == null) { - // 秒杀活动已删除时,库存已无回写对象;记日志并跳过,不阻断订单取消主流程 - log.warn("[updateSeckillStockIncr][秒杀活动({}) sku({}) 的商品配置不存在(活动可能已删除),跳过库存回写]", id, skuId); + if (product == null) { // 活动已删除,或 SKU 已从活动移除,跳过秒杀库存恢复,避免阻断订单取消 + log.warn("[updateSeckillStockIncr][活动({}) skuId({}) 对应的秒杀商品不存在,跳过库存恢复]", id, skuId); return; } // 更新活动商品库存 diff --git a/yudao-module-mall/yudao-module-promotion/src/test/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImplStockTest.java b/yudao-module-mall/yudao-module-promotion/src/test/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImplStockTest.java new file mode 100644 index 0000000..41935b5 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion/src/test/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImplStockTest.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.promotion.service.seckill; + +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * {@link SeckillActivityServiceImpl} 的库存单元测试类 + * + * @author 芋道源码 + */ +public class SeckillActivityServiceImplStockTest extends BaseMockitoUnitTest { + + @InjectMocks + private SeckillActivityServiceImpl seckillActivityService; + + @Mock + private SeckillActivityMapper seckillActivityMapper; + @Mock + private SeckillProductMapper seckillProductMapper; + + @Test + public void testUpdateSeckillStockIncr_success() { + // 准备参数 + Long id = randomLongId(); + Long skuId = randomLongId(); + Integer count = 2; + // mock 方法 + SeckillProductDO product = randomPojo(SeckillProductDO.class, o -> { + o.setActivityId(id); + o.setSkuId(skuId); + }); + when(seckillProductMapper.selectByActivityIdAndSkuId(eq(id), eq(skuId))).thenReturn(product); + + // 调用 + seckillActivityService.updateSeckillStockIncr(id, skuId, count); + // 断言 + verify(seckillProductMapper).updateStockIncr(eq(product.getId()), eq(count)); + verify(seckillActivityMapper).updateStockIncr(eq(id), eq(count)); + } + + @Test + public void testUpdateSeckillStockIncr_notExists() { + // 准备参数 + Long id = randomLongId(); + Long skuId = randomLongId(); + Integer count = 2; + // mock 方法(活动已删除,或 SKU 已从活动移除) + when(seckillProductMapper.selectByActivityIdAndSkuId(eq(id), eq(skuId))).thenReturn(null); + + // 调用 + assertDoesNotThrow(() -> seckillActivityService.updateSeckillStockIncr(id, skuId, count)); + // 断言 + verify(seckillProductMapper, never()).updateStockIncr(anyLong(), anyInt()); + verify(seckillActivityMapper, never()).updateStockIncr(anyLong(), anyInt()); + } + +}