diff --git a/src/test/java/com/ycwl/basic/facebody/adapter/AliFaceBodyAdapterTest.java b/src/test/java/com/ycwl/basic/facebody/adapter/AliFaceBodyAdapterIT.java similarity index 97% rename from src/test/java/com/ycwl/basic/facebody/adapter/AliFaceBodyAdapterTest.java rename to src/test/java/com/ycwl/basic/facebody/adapter/AliFaceBodyAdapterIT.java index 9c7f7ef2..9db049c5 100644 --- a/src/test/java/com/ycwl/basic/facebody/adapter/AliFaceBodyAdapterTest.java +++ b/src/test/java/com/ycwl/basic/facebody/adapter/AliFaceBodyAdapterIT.java @@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.junit.jupiter.api.Assertions.*; -public class AliFaceBodyAdapterTest { +public class AliFaceBodyAdapterIT { private AliFaceBodyAdapter getAdapter() { AliFaceBodyAdapter adapter = new AliFaceBodyAdapter(); AliFaceBodyConfig config = new AliFaceBodyConfig(); diff --git a/src/test/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapterTest.java b/src/test/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapterIT.java similarity index 99% rename from src/test/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapterTest.java rename to src/test/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapterIT.java index f59dcc97..775bd635 100644 --- a/src/test/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapterTest.java +++ b/src/test/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapterIT.java @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.*; @Slf4j @SpringBootTest @RunWith(SpringRunner.class) -public class BceFaceBodyAdapterTest { +public class BceFaceBodyAdapterIT { @Autowired private FaceSampleMapper faceSampleMapper; diff --git a/src/test/java/com/ycwl/basic/pricing/service/CouponServiceImplTest.java b/src/test/java/com/ycwl/basic/pricing/service/CouponServiceImplTest.java index 592c211c..1acd9f70 100644 --- a/src/test/java/com/ycwl/basic/pricing/service/CouponServiceImplTest.java +++ b/src/test/java/com/ycwl/basic/pricing/service/CouponServiceImplTest.java @@ -87,7 +87,6 @@ class CouponServiceImplTest { PriceCouponConfig coupon = baseCoupon(); coupon.setClaimedQuantity(9); when(couponConfigMapper.selectById(1L)).thenReturn(coupon); - when(couponClaimRecordMapper.countUserCouponClaims(10L, 1L)).thenReturn(0); when(couponClaimRecordMapper.insert(any())).thenReturn(1); when(couponConfigMapper.incrementClaimedQuantityIfAvailable(1L)).thenReturn(0); @@ -116,6 +115,7 @@ class CouponServiceImplTest { coupon.setValidUntil(new Date(now.getTime() + oneDayMillis)); coupon.setTotalQuantity(100); coupon.setClaimedQuantity(0); + coupon.setDeleted(0); return coupon; } } diff --git a/src/test/java/com/ycwl/basic/pricing/service/NewPhotoPrintSkuTest.java b/src/test/java/com/ycwl/basic/pricing/service/NewPhotoPrintSkuTest.java index 5d17a475..64661bc8 100644 --- a/src/test/java/com/ycwl/basic/pricing/service/NewPhotoPrintSkuTest.java +++ b/src/test/java/com/ycwl/basic/pricing/service/NewPhotoPrintSkuTest.java @@ -1,12 +1,15 @@ package com.ycwl.basic.pricing.service; +import com.ycwl.basic.pricing.dto.DiscountCombinationResult; import com.ycwl.basic.pricing.dto.PriceCalculationRequest; import com.ycwl.basic.pricing.dto.PriceCalculationResult; import com.ycwl.basic.pricing.dto.ProductItem; -import com.ycwl.basic.pricing.dto.ProductPriceInfo; import com.ycwl.basic.pricing.entity.PriceProductConfig; import com.ycwl.basic.pricing.enums.ProductType; import com.ycwl.basic.pricing.service.impl.PriceCalculationServiceImpl; +import com.ycwl.basic.product.capability.PricingMode; +import com.ycwl.basic.product.capability.ProductTypeCapability; +import com.ycwl.basic.product.service.IProductTypeCapabilityService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -50,12 +53,18 @@ class NewPhotoPrintSkuTest { @Mock private IVoucherService voucherService; + @Mock + private IProductTypeCapabilityService productTypeCapabilityService; + @InjectMocks private PriceCalculationServiceImpl priceCalculationService; @BeforeEach void setUp() { - // 初始化设置(如有需要) + ProductTypeCapability capability = new ProductTypeCapability(); + capability.setPricingModeEnum(PricingMode.QUANTITY_BASED); + lenient().when(productTypeCapabilityService.getCapability(anyString())).thenReturn(capability); + lenient().when(discountDetectionService.previewOptimalCombination(any())).thenReturn(buildEmptyDiscountResult()); } /** @@ -98,9 +107,9 @@ class NewPhotoPrintSkuTest { config.setOriginalPrice(originalPrice); // Mock 服务行为 - when(productConfigService.getTierConfig(anyString(), anyString(), anyInt())) + when(productConfigService.getTierConfig(anyString(), anyString(), anyInt(), isNull())) .thenReturn(null); // 不使用阶梯定价 - when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default", null)) .thenReturn(config); // 构建请求 @@ -124,7 +133,7 @@ class NewPhotoPrintSkuTest { // 验证服务调用 verify(productConfigService, atLeastOnce()) - .getProductConfig("PHOTO_PRINT_MU", "default"); + .getProductConfig("PHOTO_PRINT_MU", "default", null); } /** @@ -145,9 +154,9 @@ class NewPhotoPrintSkuTest { config.setOriginalPrice(originalPrice); // Mock 服务行为 - when(productConfigService.getTierConfig(anyString(), anyString(), anyInt())) + when(productConfigService.getTierConfig(anyString(), anyString(), anyInt(), isNull())) .thenReturn(null); - when(productConfigService.getProductConfig("PHOTO_PRINT_FX", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT_FX", "default", null)) .thenReturn(config); // 构建请求 @@ -170,7 +179,7 @@ class NewPhotoPrintSkuTest { .compareTo(result.getFinalAmount())); // 5.00 * 15 = 75.00 verify(productConfigService, atLeastOnce()) - .getProductConfig("PHOTO_PRINT_FX", "default"); + .getProductConfig("PHOTO_PRINT_FX", "default", null); } /** @@ -187,10 +196,11 @@ class NewPhotoPrintSkuTest { scenicConfig.setProductType("PHOTO_PRINT_MU"); scenicConfig.setProductId(scenicId); scenicConfig.setBasePrice(scenicPrice); + scenicConfig.setOriginalPrice(scenicPrice); - when(productConfigService.getTierConfig(anyString(), anyString(), anyInt())) + when(productConfigService.getTierConfig(anyString(), anyString(), anyInt(), isNull())) .thenReturn(null); - when(productConfigService.getProductConfig("PHOTO_PRINT_MU", scenicId)) + when(productConfigService.getProductConfig("PHOTO_PRINT_MU", scenicId, null)) .thenReturn(scenicConfig); ProductItem item = new ProductItem(); @@ -210,7 +220,7 @@ class NewPhotoPrintSkuTest { assertEquals(0, scenicPrice.multiply(BigDecimal.valueOf(quantity)) .compareTo(result.getFinalAmount())); - verify(productConfigService).getProductConfig("PHOTO_PRINT_MU", scenicId); + verify(productConfigService).getProductConfig("PHOTO_PRINT_MU", scenicId, null); } /** @@ -227,14 +237,15 @@ class NewPhotoPrintSkuTest { defaultConfig.setProductType("PHOTO_PRINT_MU"); defaultConfig.setProductId("default"); defaultConfig.setBasePrice(defaultPrice); + defaultConfig.setOriginalPrice(defaultPrice); // 景区配置不存在,抛出异常 - when(productConfigService.getTierConfig(anyString(), anyString(), anyInt())) + when(productConfigService.getTierConfig(anyString(), anyString(), anyInt(), isNull())) .thenReturn(null); - when(productConfigService.getProductConfig("PHOTO_PRINT_MU", scenicId)) + when(productConfigService.getProductConfig("PHOTO_PRINT_MU", scenicId, null)) .thenThrow(new RuntimeException("Not found")); // 回退到 default 配置 - when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default", null)) .thenReturn(defaultConfig); ProductItem item = new ProductItem(); @@ -255,9 +266,9 @@ class NewPhotoPrintSkuTest { .compareTo(result.getFinalAmount())); // 验证回退逻辑被调用 - verify(productConfigService).getProductConfig("PHOTO_PRINT_MU", scenicId); + verify(productConfigService).getProductConfig("PHOTO_PRINT_MU", scenicId, null); verify(productConfigService, atLeastOnce()) - .getProductConfig("PHOTO_PRINT_MU", "default"); + .getProductConfig("PHOTO_PRINT_MU", "default", null); } /** @@ -275,13 +286,13 @@ class NewPhotoPrintSkuTest { PriceProductConfig photoPrintMuConfig = createConfig("PHOTO_PRINT_MU", unitPrice); PriceProductConfig photoPrintFxConfig = createConfig("PHOTO_PRINT_FX", unitPrice); - when(productConfigService.getTierConfig(anyString(), anyString(), anyInt())) + when(productConfigService.getTierConfig(anyString(), anyString(), anyInt(), isNull())) .thenReturn(null); - when(productConfigService.getProductConfig("PHOTO_PRINT", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT", "default", null)) .thenReturn(photoPrintConfig); - when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default", null)) .thenReturn(photoPrintMuConfig); - when(productConfigService.getProductConfig("PHOTO_PRINT_FX", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT_FX", "default", null)) .thenReturn(photoPrintFxConfig); // 测试 PHOTO_PRINT @@ -309,10 +320,11 @@ class NewPhotoPrintSkuTest { config.setProductType("PHOTO_PRINT_MU"); config.setProductId("default"); config.setBasePrice(unitPrice); + config.setOriginalPrice(unitPrice); - when(productConfigService.getTierConfig(anyString(), anyString(), anyInt())) + when(productConfigService.getTierConfig(anyString(), anyString(), anyInt(), isNull())) .thenReturn(null); - when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default")) + when(productConfigService.getProductConfig("PHOTO_PRINT_MU", "default", null)) .thenReturn(config); // 测试数量为0 @@ -334,9 +346,19 @@ class NewPhotoPrintSkuTest { config.setProductType(productType); config.setProductId("default"); config.setBasePrice(basePrice); + config.setOriginalPrice(basePrice); return config; } + private DiscountCombinationResult buildEmptyDiscountResult() { + DiscountCombinationResult result = new DiscountCombinationResult(); + result.setSuccess(true); + result.setDiscountDetails(Collections.emptyList()); + result.setAppliedDiscounts(Collections.emptyList()); + result.setAvailableDiscounts(Collections.emptyList()); + return result; + } + /** * 执行价格计算的辅助方法 */ diff --git a/src/test/java/com/ycwl/basic/pricing/service/ReusableVoucherServiceTest.java b/src/test/java/com/ycwl/basic/pricing/service/ReusableVoucherServiceTest.java index a36e7842..ef5c8026 100644 --- a/src/test/java/com/ycwl/basic/pricing/service/ReusableVoucherServiceTest.java +++ b/src/test/java/com/ycwl/basic/pricing/service/ReusableVoucherServiceTest.java @@ -109,7 +109,7 @@ public class ReusableVoucherServiceTest { // Then assertNotNull(result); assertFalse(result.getAvailable()); - assertEquals("券码已用完", result.getUnavailableReason()); + assertEquals("券码使用次数已达上限", result.getUnavailableReason()); } @Test @@ -203,4 +203,4 @@ public class ReusableVoucherServiceTest { voucherCode.getUsedTime() != null )); } -} \ No newline at end of file +} diff --git a/src/test/java/com/ycwl/basic/pricing/service/VoucherTimeRangeTest.java b/src/test/java/com/ycwl/basic/pricing/service/VoucherTimeRangeTest.java index 01f9321e..d6c1b5d1 100644 --- a/src/test/java/com/ycwl/basic/pricing/service/VoucherTimeRangeTest.java +++ b/src/test/java/com/ycwl/basic/pricing/service/VoucherTimeRangeTest.java @@ -5,14 +5,9 @@ import com.ycwl.basic.pricing.dto.req.VoucherBatchCreateReqV2; import com.ycwl.basic.pricing.entity.PriceVoucherBatchConfig; import com.ycwl.basic.pricing.enums.ProductType; import com.ycwl.basic.pricing.enums.VoucherDiscountType; -import com.ycwl.basic.pricing.service.impl.VoucherServiceImpl; -import com.ycwl.basic.pricing.service.impl.VoucherBatchServiceImpl; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.test.context.ActiveProfiles; import java.math.BigDecimal; import java.util.Arrays; @@ -24,22 +19,13 @@ import static org.junit.jupiter.api.Assertions.*; /** * 券码时间范围功能单元测试 */ -@SpringBootTest -@ActiveProfiles("test") -@Transactional public class VoucherTimeRangeTest { - - private VoucherServiceImpl voucherService; - private VoucherBatchServiceImpl voucherBatchService; private Long testScenicId = 1001L; private Long testBrokerId = 2001L; - private Long testFaceId = 3001L; @BeforeEach void setUp() { - // 这里应该注入真实的服务实例,或者使用Mock - // 为了演示,这里只是创建测试结构 } @Test @@ -243,4 +229,4 @@ public class VoucherTimeRangeTest { } } } -} \ No newline at end of file +} diff --git a/src/test/java/com/ycwl/basic/pricing/service/impl/PriceCalculationServiceImplUpgradeCheckTest.java b/src/test/java/com/ycwl/basic/pricing/service/impl/PriceCalculationServiceImplUpgradeCheckTest.java new file mode 100644 index 00000000..f7954303 --- /dev/null +++ b/src/test/java/com/ycwl/basic/pricing/service/impl/PriceCalculationServiceImplUpgradeCheckTest.java @@ -0,0 +1,156 @@ +package com.ycwl.basic.pricing.service.impl; + +import com.ycwl.basic.order.service.IOrderService; +import com.ycwl.basic.pricing.dto.OnePriceInfo; +import com.ycwl.basic.pricing.dto.ProductItem; +import com.ycwl.basic.pricing.dto.UpgradeCheckRequest; +import com.ycwl.basic.pricing.dto.UpgradeCheckResult; +import com.ycwl.basic.pricing.entity.PriceBundleConfig; +import com.ycwl.basic.pricing.entity.PriceProductConfig; +import com.ycwl.basic.pricing.enums.ProductType; +import com.ycwl.basic.pricing.service.ICouponService; +import com.ycwl.basic.pricing.service.IDiscountDetectionService; +import com.ycwl.basic.pricing.service.IOnePricePurchaseService; +import com.ycwl.basic.pricing.service.IPriceBundleService; +import com.ycwl.basic.pricing.service.IProductConfigService; +import com.ycwl.basic.pricing.service.IVoucherService; +import com.ycwl.basic.product.service.IProductTypeCapabilityService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.math.BigDecimal; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class PriceCalculationServiceImplUpgradeCheckTest { + + @Mock + private IProductConfigService productConfigService; + @Mock + private ICouponService couponService; + @Mock + private IPriceBundleService bundleService; + @Mock + private IOnePricePurchaseService onePricePurchaseService; + @Mock + private IDiscountDetectionService discountDetectionService; + @Mock + private IVoucherService voucherService; + @Mock + private IProductTypeCapabilityService productTypeCapabilityService; + @Mock + private IOrderService orderService; + + @InjectMocks + private PriceCalculationServiceImpl priceCalculationService; + + @Test + void shouldSelectOnePriceWhenUpgradeTypeSpecified() { + mockProductConfig(new BigDecimal("100.00")); + when(onePricePurchaseService.getOnePriceInfo(eq(1L), any())) + .thenReturn(buildOnePriceInfo(new BigDecimal("80.00"))); + when(bundleService.getCheapestBundleConfig(any())) + .thenReturn(buildBundleConfig(new BigDecimal("50.00"))); + + UpgradeCheckRequest request = buildRequest("ONE_PRICE"); + UpgradeCheckResult result = priceCalculationService.checkUpgrade(request); + + assertEquals("ONE_PRICE", result.getBestUpgradeType()); + assertEquals(new BigDecimal("80.00"), result.getBestPayableAmount()); + } + + @Test + void shouldSelectCheapestBundleWhenUpgradeTypeMissing() { + mockProductConfig(new BigDecimal("100.00")); + when(onePricePurchaseService.getOnePriceInfo(eq(1L), any())) + .thenReturn(buildOnePriceInfo(new BigDecimal("80.00"))); + when(bundleService.getCheapestBundleConfig(any())) + .thenReturn(buildBundleConfig(new BigDecimal("70.00"))); + + UpgradeCheckRequest request = buildRequest(null); + UpgradeCheckResult result = priceCalculationService.checkUpgrade(request); + + assertEquals("BUNDLE_DISCOUNT", result.getBestUpgradeType()); + assertEquals(new BigDecimal("70.00"), result.getBestPayableAmount()); + } + + @Test + void shouldReturnNullBestWhenOnePriceNotApplicable() { + mockProductConfig(new BigDecimal("100.00")); + when(onePricePurchaseService.getOnePriceInfo(eq(1L), any())) + .thenReturn(buildOnePriceInfo(new BigDecimal("120.00"))); + when(bundleService.getCheapestBundleConfig(any())) + .thenReturn(buildBundleConfig(new BigDecimal("70.00"))); + + UpgradeCheckRequest request = buildRequest("ONE_PRICE"); + UpgradeCheckResult result = priceCalculationService.checkUpgrade(request); + + assertNull(result.getBestUpgradeType()); + assertNull(result.getBestPayableAmount()); + } + + private void mockProductConfig(BigDecimal basePrice) { + PriceProductConfig config = new PriceProductConfig(); + config.setProductType(ProductType.PHOTO_SET.getCode()); + config.setProductId("p1"); + config.setBasePrice(basePrice); + config.setOriginalPrice(basePrice); + config.setProductName("照片集"); + + when(productConfigService.getProductConfig(anyString(), anyString(), anyLong())) + .thenReturn(config); + } + + private UpgradeCheckRequest buildRequest(String upgradeType) { + UpgradeCheckRequest request = new UpgradeCheckRequest(); + request.setScenicId(1L); + request.setFaceId(2L); + request.setMemberId(3L); + request.setPaidAmount(BigDecimal.ZERO); + request.setPurchasedProducts(List.of()); + request.setIntendingProducts(List.of(buildProductItem())); + request.setUpgradeType(upgradeType); + return request; + } + + private ProductItem buildProductItem() { + ProductItem item = new ProductItem(); + item.setProductType(ProductType.PHOTO_SET); + item.setProductId("p1"); + item.setQuantity(1); + item.setPurchaseCount(1); + return item; + } + + private OnePriceInfo buildOnePriceInfo(BigDecimal onePrice) { + OnePriceInfo info = new OnePriceInfo(); + info.setConfigId(10L); + info.setConfigName("一口价"); + info.setScenicId(1L); + info.setOnePrice(onePrice); + info.setOriginalPrice(onePrice); + info.setDescription("一口价测试"); + return info; + } + + private PriceBundleConfig buildBundleConfig(BigDecimal bundlePrice) { + PriceBundleConfig config = new PriceBundleConfig(); + config.setId(20L); + config.setBundleName("打包购买"); + config.setBundlePrice(bundlePrice); + config.setScenicId("1"); + config.setDescription("打包购买测试"); + return config; + } +} diff --git a/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceTest.java b/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceIT.java similarity index 88% rename from src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceTest.java rename to src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceIT.java index dae22296..8c8b1a8a 100644 --- a/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceTest.java +++ b/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceIT.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; -class CustomUploadTaskServiceTest { +class CustomUploadTaskServiceIT { @Test void handleAliyunMpsJobComplete() { diff --git a/src/test/java/com/ycwl/basic/task/FaceCleanerTest.java b/src/test/java/com/ycwl/basic/task/FaceCleanerIT.java similarity index 99% rename from src/test/java/com/ycwl/basic/task/FaceCleanerTest.java rename to src/test/java/com/ycwl/basic/task/FaceCleanerIT.java index d144ef0d..2eaebabf 100644 --- a/src/test/java/com/ycwl/basic/task/FaceCleanerTest.java +++ b/src/test/java/com/ycwl/basic/task/FaceCleanerIT.java @@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit; @Slf4j @SpringBootTest @RunWith(SpringRunner.class) -public class FaceCleanerTest { +public class FaceCleanerIT { @Autowired private FaceMapper faceMapper; @Autowired diff --git a/src/test/java/com/ycwl/basic/task/ScenicStatsTaskTest.java b/src/test/java/com/ycwl/basic/task/ScenicStatsTaskIT.java similarity index 98% rename from src/test/java/com/ycwl/basic/task/ScenicStatsTaskTest.java rename to src/test/java/com/ycwl/basic/task/ScenicStatsTaskIT.java index a0c8e1aa..9a7c9553 100644 --- a/src/test/java/com/ycwl/basic/task/ScenicStatsTaskTest.java +++ b/src/test/java/com/ycwl/basic/task/ScenicStatsTaskIT.java @@ -24,7 +24,7 @@ import java.util.List; @Slf4j @SpringBootTest @RunWith(SpringRunner.class) -public class ScenicStatsTaskTest { +public class ScenicStatsTaskIT { @Autowired private ScenicStatsTask task; @Autowired