package com.ruoyi.system.service.impl; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.system.domain.PromotionCouponBatch; import com.ruoyi.system.domain.PromotionCouponRule; import com.ruoyi.system.mapper.PosFoodMapper; import com.ruoyi.system.mapper.PromotionCouponBatchMapper; import com.ruoyi.system.mapper.PromotionCouponRuleMapper; import com.ruoyi.system.service.ISysConfigService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; import java.math.BigDecimal; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class PromotionCouponBatchServiceImplDiscountLimitTest { @Mock private PromotionCouponBatchMapper batchMapper; @Mock private PromotionCouponRuleMapper ruleMapper; @Mock private ISysConfigService configService; @Mock private PosFoodMapper posFoodMapper; private PromotionCouponBatchServiceImpl service; @BeforeEach void setUp() { when(configService.selectConfigByKey("promotion.discount.limit.enabled")) .thenReturn("true"); when(configService.selectConfigByKey("promotion.discount.limit.ratio")) .thenReturn("20"); PromotionDiscountLimitChecker checker = new PromotionDiscountLimitChecker(); ReflectionTestUtils.setField(checker, "configService", configService); ReflectionTestUtils.setField(checker, "posFoodMapper", posFoodMapper); service = new PromotionCouponBatchServiceImpl(); ReflectionTestUtils.setField(service, "promotionCouponBatchMapper", batchMapper); ReflectionTestUtils.setField(service, "ruleMapper", ruleMapper); ReflectionTestUtils.setField(service, "discountLimitChecker", checker); } @Test void createRejectsOverLimitCouponBeforeAnyDatabaseWrite() { PromotionCouponBatch batch = batch(null, 1, 100, 0); PromotionCouponRule rule = fullReductionRule("100", "21"); assertThrows(ServiceException.class, () -> service.createBatch(batch, rule)); verifyNoInteractions(batchMapper, ruleMapper); } @Test void unreceivedCouponUpdateRejectsOverLimitRuleBeforeReplacingStoredData() { PromotionCouponBatch existing = batch(7L, 1, 100, 0); existing.setStatus(0); existing.setRemainCount(100); when(batchMapper.selectById(7L)).thenReturn(existing); PromotionCouponBatch update = batch(7L, null, 100, null); assertThrows(ServiceException.class, () -> service.updateBatch(update, fullReductionRule("100", "21"))); verify(batchMapper).selectById(7L); verify(batchMapper, never()).updateById(any(PromotionCouponBatch.class)); verifyNoInteractions(ruleMapper); } private PromotionCouponBatch batch(Long id, Integer type, Integer totalCount, Integer receivedCount) { PromotionCouponBatch batch = new PromotionCouponBatch(); batch.setId(id); batch.setCouponType(type); batch.setTotalCount(totalCount); batch.setReceivedCount(receivedCount); return batch; } private PromotionCouponRule fullReductionRule(String threshold, String amount) { PromotionCouponRule rule = new PromotionCouponRule(); rule.setThreshold(new BigDecimal(threshold)); rule.setAmount(new BigDecimal(amount)); return rule; } }