Commit b7fab2643511a259b819beddcd87f4927abd972e
1 parent
75033900
test(promotion): 补充秒杀库存回补回归测试
- 覆盖秒杀商品配置不存在时跳过库存恢复、正常配置同时恢复商品与活动库存 - 精简判空分支注释和日志,对齐项目代码风格 关联 PR: #1266 关联 issue: #1265
Showing
2 changed files
with
74 additions
and
3 deletions
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 { | @@ -188,9 +188,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 188 | @Transactional(rollbackFor = Exception.class) | 188 | @Transactional(rollbackFor = Exception.class) |
| 189 | public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { | 189 | public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { |
| 190 | SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId); | 190 | SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId); |
| 191 | - if (product == null) { | ||
| 192 | - // 秒杀活动已删除时,库存已无回写对象;记日志并跳过,不阻断订单取消主流程 | ||
| 193 | - log.warn("[updateSeckillStockIncr][秒杀活动({}) sku({}) 的商品配置不存在(活动可能已删除),跳过库存回写]", id, skuId); | 191 | + if (product == null) { // 活动已删除,或 SKU 已从活动移除,跳过秒杀库存恢复,避免阻断订单取消 |
| 192 | + log.warn("[updateSeckillStockIncr][活动({}) skuId({}) 对应的秒杀商品不存在,跳过库存恢复]", id, skuId); | ||
| 194 | return; | 193 | return; |
| 195 | } | 194 | } |
| 196 | // 更新活动商品库存 | 195 | // 更新活动商品库存 |
yudao-module-mall/yudao-module-promotion/src/test/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImplStockTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.service.seckill; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 4 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; | ||
| 5 | +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper; | ||
| 6 | +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper; | ||
| 7 | +import org.junit.jupiter.api.Test; | ||
| 8 | +import org.mockito.InjectMocks; | ||
| 9 | +import org.mockito.Mock; | ||
| 10 | + | ||
| 11 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | ||
| 12 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 13 | +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | ||
| 14 | +import static org.mockito.ArgumentMatchers.anyInt; | ||
| 15 | +import static org.mockito.ArgumentMatchers.anyLong; | ||
| 16 | +import static org.mockito.ArgumentMatchers.eq; | ||
| 17 | +import static org.mockito.Mockito.never; | ||
| 18 | +import static org.mockito.Mockito.verify; | ||
| 19 | +import static org.mockito.Mockito.when; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * {@link SeckillActivityServiceImpl} 的库存单元测试类 | ||
| 23 | + * | ||
| 24 | + * @author 芋道源码 | ||
| 25 | + */ | ||
| 26 | +public class SeckillActivityServiceImplStockTest extends BaseMockitoUnitTest { | ||
| 27 | + | ||
| 28 | + @InjectMocks | ||
| 29 | + private SeckillActivityServiceImpl seckillActivityService; | ||
| 30 | + | ||
| 31 | + @Mock | ||
| 32 | + private SeckillActivityMapper seckillActivityMapper; | ||
| 33 | + @Mock | ||
| 34 | + private SeckillProductMapper seckillProductMapper; | ||
| 35 | + | ||
| 36 | + @Test | ||
| 37 | + public void testUpdateSeckillStockIncr_success() { | ||
| 38 | + // 准备参数 | ||
| 39 | + Long id = randomLongId(); | ||
| 40 | + Long skuId = randomLongId(); | ||
| 41 | + Integer count = 2; | ||
| 42 | + // mock 方法 | ||
| 43 | + SeckillProductDO product = randomPojo(SeckillProductDO.class, o -> { | ||
| 44 | + o.setActivityId(id); | ||
| 45 | + o.setSkuId(skuId); | ||
| 46 | + }); | ||
| 47 | + when(seckillProductMapper.selectByActivityIdAndSkuId(eq(id), eq(skuId))).thenReturn(product); | ||
| 48 | + | ||
| 49 | + // 调用 | ||
| 50 | + seckillActivityService.updateSeckillStockIncr(id, skuId, count); | ||
| 51 | + // 断言 | ||
| 52 | + verify(seckillProductMapper).updateStockIncr(eq(product.getId()), eq(count)); | ||
| 53 | + verify(seckillActivityMapper).updateStockIncr(eq(id), eq(count)); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @Test | ||
| 57 | + public void testUpdateSeckillStockIncr_notExists() { | ||
| 58 | + // 准备参数 | ||
| 59 | + Long id = randomLongId(); | ||
| 60 | + Long skuId = randomLongId(); | ||
| 61 | + Integer count = 2; | ||
| 62 | + // mock 方法(活动已删除,或 SKU 已从活动移除) | ||
| 63 | + when(seckillProductMapper.selectByActivityIdAndSkuId(eq(id), eq(skuId))).thenReturn(null); | ||
| 64 | + | ||
| 65 | + // 调用 | ||
| 66 | + assertDoesNotThrow(() -> seckillActivityService.updateSeckillStockIncr(id, skuId, count)); | ||
| 67 | + // 断言 | ||
| 68 | + verify(seckillProductMapper, never()).updateStockIncr(anyLong(), anyInt()); | ||
| 69 | + verify(seckillActivityMapper, never()).updateStockIncr(anyLong(), anyInt()); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | +} |