From 000561171a4778a4fc19f403f5794705bce5998f Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Tue, 20 Jan 2026 14:44:20 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81WithMockLoginUser=E4=BB=8ESecurity?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E6=96=87=E6=94=B9=E4=B8=BA=E7=BA=AFmock?= =?UTF-8?q?=EF=BC=9B2=E3=80=81=E6=9B=B4=E6=96=B0=E8=B5=84=E9=87=91?= =?UTF-8?q?=E7=AE=A1=E7=90=86service=E5=89=A5=E7=A6=BB=E7=9C=9F=E5=AE=9Eh2?= =?UTF-8?q?db=EF=BC=8C=E9=87=87=E7=94=A8=E7=BA=AFmock=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/test/WithMockLoginUser.java | 6 +- .../funds/invoice/InvoiceServiceImpl.java | 2 +- .../funds/products/ProductsServiceImpl.java | 3 - .../common/WithMockLoginUserExtension.java | 54 ++ .../delay/ProductDelayServiceImplTest.java | 661 +++++++----------- .../IncomeExpenseServiceImplTest.java | 64 +- .../funds/invoice/InvoiceServiceImplTest.java | 382 +++++----- .../OrganAmountServiceImplTest.java | 99 ++- .../ProductPromotionServiceImplTest.java | 210 +++--- .../ProductsDetailServiceImplTest.java | 116 +-- .../products/ProductsServiceImplTest.java | 171 +++-- .../purchase/PurchaseServiceImplTest.java | 522 ++++++-------- .../FundsStatisticsServiceImplTest.java | 56 +- 13 files changed, 1034 insertions(+), 1312 deletions(-) create mode 100644 cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/common/WithMockLoginUserExtension.java diff --git a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/test/WithMockLoginUser.java b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/test/WithMockLoginUser.java index 5d540f301..19ca12650 100644 --- a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/test/WithMockLoginUser.java +++ b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/test/WithMockLoginUser.java @@ -1,9 +1,9 @@ package com.cf.imes.framework.security.test; -import org.springframework.security.test.context.support.WithSecurityContext; - +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * security mock loginuser annotation @@ -12,7 +12,7 @@ import java.lang.annotation.RetentionPolicy; * @since 2025/9/8 11:16 */ @Retention(RetentionPolicy.RUNTIME) -@WithSecurityContext(factory = WithMockLoginUserSecurityContextFactory.class) +@Target(ElementType.METHOD) public @interface WithMockLoginUser { long userId() default 0L; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java index 36cd5738c..b2efb83f7 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java @@ -434,7 +434,7 @@ public class InvoiceServiceImpl implements InvoiceService { * @return */ private List validatePurchaseRecordExists(List purchaseId) { - List purchaseRecordDOS = purchaseRecordMapper.selectBatchIds(purchaseId); + List purchaseRecordDOS = purchaseRecordMapper.selectByIds(purchaseId); if (CollUtil.isEmpty(purchaseRecordDOS)) { throw new ServiceException(PURCHASE_RECORD_NO_EXIST); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java index a5bc285f8..c305ec39b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java @@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.Assert.AssertUtils; -import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductPageReqVO; @@ -65,8 +64,6 @@ public class ProductsServiceImpl implements ProductsService { if (ProductStatusEnum.PRODUCT_UPDATES.getStatus().equals(status) && !ProductStatusEnum.isProductDelis(updateReqVOStatus)) { throw new ServiceException(PRODUCTS_NO_UPDATE); } - ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class); - productsMapper.updateById(productsDO); productsMapper.update(new LambdaUpdateWrapperX() .eq(ProductsDO::getId, updateReqVOId) .setIfPresent(ProductsDO::getProductName, productName) diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/common/WithMockLoginUserExtension.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/common/WithMockLoginUserExtension.java new file mode 100644 index 000000000..fba45cb0d --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/common/WithMockLoginUserExtension.java @@ -0,0 +1,54 @@ +package com.cf.imes.module.system.common; + +import com.cf.imes.framework.security.core.LoginUser; +import com.cf.imes.framework.security.test.WithMockLoginUser; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.mockito.Mockito; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * + * + * @author Gqr + * @since 2026/1/16 10:20 + */ +public class WithMockLoginUserExtension implements BeforeEachCallback, AfterEachCallback { + @Override + public void afterEach(ExtensionContext context) { + SecurityContextHolder.clearContext(); + } + + @Override + public void beforeEach(ExtensionContext context) { + WithMockLoginUser ann = findAnnotation(context); + + LoginUser loginUser = new LoginUser(); + if (ann != null) { + loginUser.setId(ann.userId()); + loginUser.setOrganId(ann.organId()); + loginUser.setDeptId(ann.deptId()); + loginUser.setNickname(ann.username()); + } else { + return; + } + + Authentication authentication = Mockito.mock(Authentication.class); + Mockito.when(authentication.getPrincipal()).thenReturn(loginUser); + + SecurityContext securityContext = Mockito.mock(SecurityContext.class); + Mockito.when(securityContext.getAuthentication()) + .thenReturn(authentication); + + SecurityContextHolder.setContext(securityContext); + } + + private WithMockLoginUser findAnnotation(ExtensionContext context) { + return context.getElement() + .map(el -> el.getAnnotation(WithMockLoginUser.class)) + .orElse(null); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImplTest.java index 2e0bb48aa..f8018a00d 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImplTest.java @@ -1,7 +1,10 @@ package com.cf.imes.module.system.service.funds.delay; +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.controller.admin.funds.delay.vo.PreviouProductDelayRespVO; import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayPageReqVO; import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; @@ -12,481 +15,353 @@ import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO; import com.cf.imes.module.system.dal.mysql.funds.delay.ProductDelayRecordMapper; import com.cf.imes.module.system.dal.mysql.funds.purchase.PurchaseRecordMapper; import com.cf.imes.module.system.enums.pay.DurationUnitEnum; -import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum; -import com.cf.imes.module.system.enums.pay.PurchaseRecordStatusEnum; -import com.cf.imes.module.system.service.funds.products.ProductsDetailService; import com.cf.imes.module.system.service.funds.purchase.PurchaseService; import com.cf.imes.module.system.service.organ.OrganService; -import jakarta.annotation.Resource; +import org.apache.ibatis.builder.MapperBuilderAssistant; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.time.LocalDate; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException; -import static com.cf.imes.framework.test.core.util.RandomUtils.randomLongId; -import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_DELAY_UNIT_NOT_SUPPORT; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PURCHASE_NO_EXIST; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -/** - * {@link ProductDelayServiceImpl} 的单元测试类 - * - * @author Gqr - * @since 2025/12/8 14:30 - */ -@Import(ProductDelayServiceImpl.class) -public class ProductDelayServiceImplTest extends BaseDbAndRedisUnitTest { +class ProductDelayServiceImplTest extends BaseMockitoUnitTest { - @Resource + @InjectMocks private ProductDelayServiceImpl productDelayService; - @Resource - private ProductDelayRecordMapper recordMapper; + @Mock + private ProductDelayRecordMapper productDelayRecordMapper; - @Resource + @Mock private PurchaseRecordMapper purchaseRecordMapper; - @MockitoBean + @Mock private OrganService organService; - @MockitoBean + @Mock private PurchaseService purchaseService; - @MockitoBean - private ProductsDetailService productsDetailService; - - @Test - public void testCreateProductDelay_noPreDelayRecord_success() { - // 准备参数 - Long organId = randomLongId(); - Long purchaseId = randomLongId(); - Long productId = randomLongId(); - - // Mock 组织 - OrganizationDO organization = new OrganizationDO(); - organization.setId(organId); - organization.setName("测试组织"); - when(organService.validOrgan(organId)).thenReturn(organization); - - // Mock 购买记录 - PurchaseRecordDO purchaseRecord = PurchaseRecordDO.builder() - .id(purchaseId) - .productId(productId) - .productName("测试产品") - .startTime(LocalDate.now().minusMonths(6)) - .endTime(LocalDate.now().plusMonths(6)) - .build(); - when(purchaseService.getRecord(purchaseId)).thenReturn(purchaseRecord); - - // 构造请求 - ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); - reqVO.setOrganId(organId); - reqVO.setPurchaseId(purchaseId); - reqVO.setDelayDuration(3); - reqVO.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - - // 调用 - Long delayId = productDelayService.createProductDelay(reqVO); - - // 断言 - assertNotNull(delayId); - ProductDelayRecordDO dbRecord = recordMapper.selectById(delayId); - assertNotNull(dbRecord); - assertEquals(organId, dbRecord.getOrganId()); - assertEquals("测试组织", dbRecord.getOrganName()); - assertEquals(productId, dbRecord.getProductId()); - assertEquals("测试产品", dbRecord.getProductName()); - assertEquals(3, dbRecord.getDelayDuration()); - assertEquals(DurationUnitEnum.MONTH.getCode(), dbRecord.getDelayDurationUnit()); - assertEquals(purchaseRecord.getEndTime(), dbRecord.getEndTime()); - assertEquals(purchaseRecord.getEndTime().plusMonths(3), dbRecord.getDelayTime()); - assertEquals(purchaseId, dbRecord.getPurchaseId()); - assertFalse(dbRecord.getPaid()); + @BeforeAll + static void init(){ + TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), ProductDelayRecordDO.class); } @Test - public void testCreateProductDelay_withPreDelayRecord_success() { - // 准备参数 - Long organId = randomLongId(); - Long purchaseId = randomLongId(); - Long productId = randomLongId(); - - // Mock 组织 - OrganizationDO organization = new OrganizationDO(); - organization.setId(organId); - organization.setName("测试组织"); - when(organService.validOrgan(organId)).thenReturn(organization); - - // Mock 购买记录 - PurchaseRecordDO purchaseRecord = PurchaseRecordDO.builder() - .id(purchaseId) - .productId(productId) - .productName("测试产品") - .startTime(LocalDate.now().minusMonths(6)) - .endTime(LocalDate.now().plusMonths(6)) - .build(); - when(purchaseService.getRecord(purchaseId)).thenReturn(purchaseRecord); - - // 插入前序延期记录 - ProductDelayRecordDO preDelayRecord = ProductDelayRecordDO.builder() - .organId(organId) - .organName("测试组织") - .productId(productId) - .productName("测试产品") - .delayDuration(1) - .delayDurationUnit(DurationUnitEnum.YEAR.getCode()) - .endTime(purchaseRecord.getEndTime()) - .delayTime(purchaseRecord.getEndTime().plusYears(1)) - .purchaseId(purchaseId) - .paid(true) - .build(); - recordMapper.insert(preDelayRecord); - - // 构造请求 + void testCreateProductDelay_purchaseNotExist() { ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); - reqVO.setOrganId(organId); - reqVO.setPurchaseId(purchaseId); - reqVO.setDelayDuration(6); - reqVO.setDelayDurationUnit(DurationUnitEnum.YEAR.getCode()); + reqVO.setOrganId(1L); + reqVO.setPurchaseId(10L); - // 调用 - Long delayId = productDelayService.createProductDelay(reqVO); + when(organService.validOrgan(1L)).thenReturn(new OrganizationDO()); + when(purchaseService.getRecord(10L)).thenReturn(null); - // 断言 - assertNotNull(delayId); - ProductDelayRecordDO dbRecord = recordMapper.selectById(delayId); - assertNotNull(dbRecord); - // 应该基于前序记录的延期时间计算 - assertEquals(preDelayRecord.getDelayTime(), dbRecord.getEndTime()); - assertEquals(preDelayRecord.getDelayTime().plusYears(6), dbRecord.getDelayTime()); + assertServiceException(() -> productDelayService.createProductDelay(reqVO), PRODUCT_PURCHASE_NO_EXIST); } @Test - public void testCreateProductDelay_expiredEndTime_success() { - // 准备参数 - Long organId = randomLongId(); - Long purchaseId = randomLongId(); - Long productId = randomLongId(); + void testCreateProductDelay_success_noLastDelay_notExpired() { + LocalDate now = LocalDate.now(); - // Mock 组织 - OrganizationDO organization = new OrganizationDO(); - organization.setId(organId); - organization.setName("测试组织"); - when(organService.validOrgan(organId)).thenReturn(organization); - - // Mock 购买记录(已过期) - PurchaseRecordDO purchaseRecord = PurchaseRecordDO.builder() - .id(purchaseId) - .productId(productId) - .productName("测试产品") - .startTime(LocalDate.now().minusMonths(12)) - .endTime(LocalDate.now().minusMonths(1)) // 已过期 - .build(); - when(purchaseService.getRecord(purchaseId)).thenReturn(purchaseRecord); - - // 构造请求 ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); - reqVO.setOrganId(organId); - reqVO.setPurchaseId(purchaseId); - reqVO.setDelayDuration(3); + reqVO.setOrganId(1L); + reqVO.setPurchaseId(100L); + reqVO.setDelayDuration(10); reqVO.setDelayDurationUnit(DurationUnitEnum.DAY.getCode()); - // 调用 - Long delayId = productDelayService.createProductDelay(reqVO); + OrganizationDO org = new OrganizationDO(); + org.setName("组织A"); - // 断言 - assertNotNull(delayId); - ProductDelayRecordDO dbRecord = recordMapper.selectById(delayId); - assertNotNull(dbRecord); - // 已过期的情况,应该从今天开始计算 - assertEquals(LocalDate.now(), dbRecord.getEndTime()); - assertEquals(LocalDate.now().plusDays(3), dbRecord.getDelayTime()); + PurchaseRecordDO purchase = new PurchaseRecordDO(); + purchase.setProductId(11L); + purchase.setProductName("产品A"); + purchase.setEndTime(now.plusDays(5)); + + when(organService.validOrgan(1L)).thenReturn(org); + when(purchaseService.getRecord(100L)).thenReturn(purchase); + when(productDelayRecordMapper.selectOne(any())).thenReturn(null); + + productDelayService.createProductDelay(reqVO); + + verify(productDelayRecordMapper).insert(argThat((ProductDelayRecordDO recordDO) -> + recordDO.getEndTime().equals(purchase.getEndTime()) + && recordDO.getDelayTime().equals(purchase.getEndTime().plusDays(10)) + && !recordDO.getPaid() + )); } @Test - public void testCreateProductDelay_withExpiredPreDelayRecord_success() { - // 准备参数 - Long organId = randomLongId(); - Long purchaseId = randomLongId(); - Long productId = randomLongId(); + void testCreateProductDelay_success_purchaseExpired() { + LocalDate now = LocalDate.now(); - // Mock 组织 - OrganizationDO organization = new OrganizationDO(); - organization.setId(organId); - organization.setName("测试组织"); - when(organService.validOrgan(organId)).thenReturn(organization); - - // Mock 购买记录(未过期) - PurchaseRecordDO purchaseRecord = PurchaseRecordDO.builder() - .id(purchaseId) - .productId(productId) - .productName("测试产品") - .startTime(LocalDate.now().minusMonths(6)) - .endTime(LocalDate.now().plusMonths(6)) - .build(); - when(purchaseService.getRecord(purchaseId)).thenReturn(purchaseRecord); - - // 插入前序延期记录(延期时间未过期) - ProductDelayRecordDO preDelayRecord = ProductDelayRecordDO.builder() - .organId(organId) - .organName("测试组织") - .productId(productId) - .productName("测试产品") - .delayDuration(3) - .delayDurationUnit(DurationUnitEnum.MONTH.getCode()) - .endTime(purchaseRecord.getEndTime()) - .delayTime(LocalDate.now().plusMonths(9)) // 未过期的延期时间 - .purchaseId(purchaseId) - .paid(true) - .build(); - recordMapper.insert(preDelayRecord); - - // 构造请求 ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); - reqVO.setOrganId(organId); - reqVO.setPurchaseId(purchaseId); - reqVO.setDelayDuration(6); - reqVO.setDelayDurationUnit(4); - - // 调用并断言异常 - assertServiceException(() -> productDelayService.createProductDelay(reqVO), - PRODUCT_DELAY_UNIT_NOT_SUPPORT); - } - - @Test - public void testCreateProductDelay_purchaseNotExist() { - // 准备参数 - Long organId = randomLongId(); - Long purchaseId = randomLongId(); - - // Mock 组织 - OrganizationDO organization = new OrganizationDO(); - organization.setId(organId); - organization.setName("测试组织"); - when(organService.validOrgan(organId)).thenReturn(organization); - - // Mock 购买记录不存在 - when(purchaseService.getRecord(purchaseId)).thenReturn(null); - - // 构造请求 - ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); - reqVO.setOrganId(organId); - reqVO.setPurchaseId(purchaseId); - reqVO.setDelayDuration(3); + reqVO.setOrganId(1L); + reqVO.setPurchaseId(200L); + reqVO.setDelayDuration(1); reqVO.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - // 调用并断言异常 - assertServiceException(() -> productDelayService.createProductDelay(reqVO), - PRODUCT_PURCHASE_NO_EXIST); + when(organService.validOrgan(any())).thenReturn(new OrganizationDO()); + when(purchaseService.getRecord(any())).thenReturn( + PurchaseRecordDO.builder() + .productId(1L) + .productName("产品") + .endTime(now.minusDays(3)) + .build() + ); + when(productDelayRecordMapper.selectOne(any())).thenReturn(null); + + productDelayService.createProductDelay(reqVO); + + verify(productDelayRecordMapper).insert(argThat((ProductDelayRecordDO r) -> + r.getEndTime().equals(now) + && r.getDelayTime().equals(now.plusMonths(1)) + )); + } + + + @Test + void testCreateProductDelay_success_withLastDelay() { + LocalDate base = LocalDate.now().plusDays(5); + + when(productDelayRecordMapper.selectOne(any())) + .thenReturn(ProductDelayRecordDO.builder() + .delayTime(base) + .build()); + + when(organService.validOrgan(any())).thenReturn(new OrganizationDO()); + when(purchaseService.getRecord(any())).thenReturn( + PurchaseRecordDO.builder() + .productId(1L) + .productName("产品") + .endTime(LocalDate.now()) + .build() + ); + + ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); + reqVO.setOrganId(1L); + reqVO.setPurchaseId(1L); + reqVO.setDelayDuration(2); + reqVO.setDelayDurationUnit(DurationUnitEnum.YEAR.getCode()); + + productDelayService.createProductDelay(reqVO); + + verify(productDelayRecordMapper).insert(argThat((ProductDelayRecordDO r) -> + r.getEndTime().equals(base) + && r.getDelayTime().equals(base.plusYears(2)) + )); } @Test - public void testGetPage() { - // mock 数据 - ProductDelayRecordDO record1 = randomPojo(ProductDelayRecordDO.class, o -> { - o.setOrganName("晨丰科技"); - o.setProductName("ERP产品"); - o.setDelayDuration(3); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - }); - recordMapper.insert(record1); + void testCreateProductDelay_unitNotSupport() { + ProductDelaySaveReqVO reqVO = new ProductDelaySaveReqVO(); + reqVO.setOrganId(1L); + reqVO.setPurchaseId(1L); + reqVO.setDelayDuration(1); + reqVO.setDelayDurationUnit(999); // 非法 - // 不匹配的数据 - recordMapper.insert(randomPojo(ProductDelayRecordDO.class, o -> { - o.setOrganName("其他组织"); - o.setProductName("ERP产品"); - o.setDelayDuration(4); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - })); + when(organService.validOrgan(any())).thenReturn(new OrganizationDO()); + when(purchaseService.getRecord(any())).thenReturn( + PurchaseRecordDO.builder() + .productId(1L) + .productName("产品") + .endTime(LocalDate.now()) + .build() + ); + when(productDelayRecordMapper.selectOne(any())).thenReturn(null); - // 准备参数 - ProductDelayPageReqVO reqVO = new ProductDelayPageReqVO(); - reqVO.setOrganName("晨丰科技"); - reqVO.setProductName("ERP产品"); - reqVO.setDelayDuration(3); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - - // 调用 - PageResult pageResult = productDelayService.getPage(reqVO); - - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - ProductDelayRespVO respVO = pageResult.getList().get(0); - assertEquals("晨丰科技", respVO.getOrganName()); - assertEquals("ERP产品", respVO.getProductName()); - assertEquals(3, respVO.getDelayDuration()); + assertServiceException(() -> productDelayService.createProductDelay(reqVO), PRODUCT_DELAY_UNIT_NOT_SUPPORT); } @Test - public void testGetRecordsByPurchaseId() { - // 准备数据 - Long purchaseId = randomLongId(); - Long organId = randomLongId(); + void testGetRecordsByPurchaseId_success() { + Long purchaseId = 100L; + Long organId = 200L; - // mock 数据 - ProductDelayRecordDO record1 = randomPojo(ProductDelayRecordDO.class, o -> { - o.setOrganName("晨丰科技"); - o.setProductName("ERP产品"); - o.setDelayDuration(3); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - o.setPurchaseId(purchaseId); - o.setOrganId(organId); - }); - recordMapper.insert(record1); + ProductDelayRecordDO recordDO = new ProductDelayRecordDO(); + recordDO.setDelayDuration(6); + recordDO.setDelayDurationUnit(2); + recordDO.setDelayTime(LocalDate.now()); - // 不匹配的数据 - recordMapper.insert(randomPojo(ProductDelayRecordDO.class, o -> { - o.setOrganName("其他组织"); - o.setProductName("ERP产品"); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - })); + when(productDelayRecordMapper.selectList(any())) + .thenReturn(List.of(recordDO)); - // 调用 - List records = productDelayService.getRecordsByPurchaseId(purchaseId, organId); + List result = + productDelayService.getRecordsByPurchaseId(purchaseId, organId); - // 断言 - assertEquals(1, records.size()); - // 验证按 ID 倒序 - assertEquals(3, records.get(0).getDelayDuration()); + assertEquals(1, result.size()); + assertEquals(6, result.get(0).getDelayDuration()); + assertEquals(2, result.get(0).getDelayDurationUnit()); + + verify(productDelayRecordMapper).selectList(any()); } @Test - public void testGetActiveRecordsByProductId_withRecords() { - // 准备数据 - Long productId = randomLongId(); - Long organId = randomLongId(); - Long purchaseId = randomLongId(); + void testGetRecordsByPurchaseId_empty() { + when(productDelayRecordMapper.selectList(any())) + .thenReturn(Collections.emptyList()); - // 插入活跃的购买记录 - PurchaseRecordDO purchaseRecord = randomPojo(PurchaseRecordDO.class, o -> { - o.setId(purchaseId); - o.setOrganId(organId); - o.setProductId(productId); - o.setStatus(PurchaseRecordStatusEnum.ACTIVE.getStatus()); - o.setCurrency(null); - o.setIsInvocing(null); - o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode()); - }); - purchaseRecordMapper.insert(purchaseRecord); + List result = + productDelayService.getRecordsByPurchaseId(1L, 1L); - // 插入延期记录 - ProductDelayRecordDO delayRecord = randomPojo(ProductDelayRecordDO.class, o -> { - o.setOrganId(organId); - o.setProductId(productId); - o.setPurchaseId(purchaseId); - o.setDelayDuration(3); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - o.setDelayTime(LocalDate.now().plusMonths(3)); - o.setEndTime(LocalDate.now()); - }); - recordMapper.insert(delayRecord); - - // 调用 - PreviouProductDelayRespVO result = productDelayService.getActiveRecordsByProductId(productId, organId); - - // 断言 assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + void testGetPage_success() { + ProductDelayPageReqVO reqVO = new ProductDelayPageReqVO(); + + ProductDelayRecordDO recordDO = new ProductDelayRecordDO(); + recordDO.setId(1L); + recordDO.setDelayDuration(3); + recordDO.setDelayDurationUnit(1); + + PageResult pageResult = + new PageResult<>(List.of(recordDO), 1L); + + when(productDelayRecordMapper.selectPage(reqVO)) + .thenReturn(pageResult); + + PageResult result = + productDelayService.getPage(reqVO); + + assertEquals(1L, result.getTotal()); + assertEquals(1, result.getList().size()); + assertEquals(3, result.getList().get(0).getDelayDuration()); + + verify(productDelayRecordMapper).selectPage(reqVO); + } + + @Test + void testGetActiveRecordsByProductId_noActivePurchase() { + Long productId = 1L; + Long organId = 2L; + + when(purchaseRecordMapper.selectOne(any())) + .thenReturn(null); + + PreviouProductDelayRespVO result = + productDelayService.getActiveRecordsByProductId(productId, organId); + + assertNotNull(result); + assertNull(result.getPreviouPurchaseRecord()); + assertTrue( + result.getDelayRespVOList() == null + || result.getDelayRespVOList().isEmpty() + ); + + verify(purchaseRecordMapper).selectOne(any()); + verifyNoInteractions(productDelayRecordMapper); + } + + @Test + void testGetActiveRecordsByProductId_success() { + Long productId = 1L; + Long organId = 2L; + + PurchaseRecordDO purchase = new PurchaseRecordDO(); + purchase.setId(10L); + purchase.setProductId(productId); + purchase.setOrganId(organId); + + ProductDelayRecordDO delay = new ProductDelayRecordDO(); + delay.setDelayDuration(3); + delay.setDelayDurationUnit(1); + delay.setDelayTime(LocalDate.now()); + + when(purchaseRecordMapper.selectOne(any())) + .thenReturn(purchase); + + when(productDelayRecordMapper.selectList(any())) + .thenReturn(List.of(delay)); + + PreviouProductDelayRespVO result = + productDelayService.getActiveRecordsByProductId(productId, organId); + + assertNotNull(result); + + // 断言 purchase assertNotNull(result.getPreviouPurchaseRecord()); - assertEquals(purchaseId, result.getPreviouPurchaseRecord().getId()); + assertEquals(10L, result.getPreviouPurchaseRecord().getId()); + + // 断言 delay 列表 assertNotNull(result.getDelayRespVOList()); assertEquals(1, result.getDelayRespVOList().size()); assertEquals(3, result.getDelayRespVOList().get(0).getDelayDuration()); + + verify(purchaseRecordMapper).selectOne(any()); + verify(productDelayRecordMapper).selectList(any()); } @Test - public void testGetActiveRecordsByProductId_noPurchaseRecord() { - // 准备数据 - Long productId = randomLongId(); - Long organId = randomLongId(); + void updatePurchaseDelayRecordsPaidAndRemark_success() { + // given + Long organId = 1L; + Boolean paid = true; - // 调用(没有购买记录) - PreviouProductDelayRespVO result = productDelayService.getActiveRecordsByProductId(productId, organId); + ProductDelayRecordDO recordDO = new ProductDelayRecordDO(); + recordDO.setId(100L); + recordDO.setRemark("test remark"); - // 断言 - assertNotNull(result); - assertNull(result.getPreviouPurchaseRecord()); - assertNull(result.getDelayRespVOList()); + List list = Collections.singletonList(recordDO); + + // mock update 行为 + when(productDelayRecordMapper.update(any(LambdaUpdateWrapper.class))) + .thenReturn(1); + + // when + productDelayService.updatePurchaseDelayRecordsPaidAndRemark(list, organId, paid); + + // then + verify(productDelayRecordMapper, times(1)) + .update(any(LambdaUpdateWrapper.class)); } - @Test - public void testUpdatePurchaseDelayRecordsPaidAndRemark() { - // 准备数据 - Long organId = randomLongId(); + void updatePurchaseDelayRecordsPaid_success() { + // given + Long purchaseId = 10L; + Long organId = 1L; - ProductDelayRecordDO record1 = randomPojo(ProductDelayRecordDO.class, o -> { - o.setPaid(false); - o.setRemark(null); - o.setDelayDuration(3); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - o.setOrganId(organId); - }); + when(productDelayRecordMapper.update(any(LambdaUpdateWrapper.class))) + .thenReturn(2); // 模拟更新 2 条 - recordMapper.insert(record1); - - // 准备更新数据 - record1.setRemark("备注1"); - List updateList = Arrays.asList(record1); - - // 调用 - productDelayService.updatePurchaseDelayRecordsPaidAndRemark(updateList, organId, true); - - // 断言 - ProductDelayRecordDO dbRecord1 = recordMapper.selectById(record1.getId()); - assertTrue(dbRecord1.getPaid()); - assertEquals("备注1", dbRecord1.getRemark()); - } - - @Test - public void testUpdatePurchaseDelayRecordsPaid() { - // 准备数据 - Long purchaseId = randomLongId(); - Long organId = randomLongId(); - - ProductDelayRecordDO record1 = randomPojo(ProductDelayRecordDO.class, o -> { - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - o.setOrganId(organId); - o.setPurchaseId(purchaseId); - o.setPaid(false); - }); - recordMapper.insert(record1); - - // 调用 + // when productDelayService.updatePurchaseDelayRecordsPaid(purchaseId, organId); - // 断言 - ProductDelayRecordDO dbRecord1 = recordMapper.selectById(record1.getId()); - assertTrue(dbRecord1.getPaid()); + // then + verify(productDelayRecordMapper, times(1)) + .update(any(LambdaUpdateWrapper.class)); } + @Test - public void testResetPurchaseDelayRecordsRemark() { - // 准备数据 - Long purchaseId = randomLongId(); - Long organId = randomLongId(); + void resetPurchaseDelayRecordsRemark_success() { + // given + Long purchaseId = 10L; + Long organId = 1L; - ProductDelayRecordDO record1 = randomPojo(ProductDelayRecordDO.class, o -> { - o.setRemark("测试备注"); - o.setDelayDuration(3); - o.setDelayDurationUnit(DurationUnitEnum.MONTH.getCode()); - o.setOrganId(organId); - o.setPurchaseId(purchaseId); - }); - recordMapper.insert(record1); + when(productDelayRecordMapper.update(any(LambdaUpdateWrapper.class))) + .thenReturn(1); - - // 调用 + // when productDelayService.resetPurchaseDelayRecordsRemark(purchaseId, organId); - // 断言 - ProductDelayRecordDO dbRecord1 = recordMapper.selectById(record1.getId()); - assertNull(dbRecord1.getRemark()); + // then + verify(productDelayRecordMapper, times(1)) + .update(any(LambdaUpdateWrapper.class)); } + } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/incomeandexpense/IncomeExpenseServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/incomeandexpense/IncomeExpenseServiceImplTest.java index 659e3bac6..ff5d664ef 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/incomeandexpense/IncomeExpenseServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/incomeandexpense/IncomeExpenseServiceImplTest.java @@ -1,64 +1,50 @@ package com.cf.imes.module.system.service.funds.incomeandexpense; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO; import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper; -import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import java.math.BigDecimal; +import org.mockito.InjectMocks; +import org.mockito.Mock; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; /** * {@link IncomeExpenseServiceImpl} 的单元测试类 * * @author Gqr */ -@Import(IncomeExpenseServiceImpl.class) -class IncomeExpenseServiceImplTest extends BaseDbAndRedisUnitTest { +class IncomeExpenseServiceImplTest extends BaseMockitoUnitTest { - @Resource + @InjectMocks private IncomeExpenseServiceImpl incomeExpenseService; - @Resource + @Mock private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper; @Test - void testCreateDetail() { - // 准备数据 - IncomeExpenseDetailsDO incomeExpenseDetailsDO = new IncomeExpenseDetailsDO(); - incomeExpenseDetailsDO.setBusinessNo("BUS20251215001"); - incomeExpenseDetailsDO.setOrderNo("ORD20251215001"); - incomeExpenseDetailsDO.setOrganId(1L); - incomeExpenseDetailsDO.setPurchaseId(100L); - incomeExpenseDetailsDO.setTradeType(1); - incomeExpenseDetailsDO.setIncomeExpenseType(2); - incomeExpenseDetailsDO.setAmount(new BigDecimal("100.00")); - incomeExpenseDetailsDO.setCurrency(1); - incomeExpenseDetailsDO.setCurrencyUnit("CNY"); - incomeExpenseDetailsDO.setRemark("测试收支明细"); + void createDetail_success() { + // given + IncomeExpenseDetailsDO detailDO = new IncomeExpenseDetailsDO(); - // 调用方法 - Long id = incomeExpenseService.createDetail(incomeExpenseDetailsDO); + doAnswer(invocation -> { + IncomeExpenseDetailsDO arg = invocation.getArgument(0); + arg.setId(100L); // 手动回填 ID + return 1; + }).when(incomeExpenseDetailsMapper).insert(any(IncomeExpenseDetailsDO.class)); - // 验证结果 + // when + Long id = incomeExpenseService.createDetail(detailDO); + + // then assertNotNull(id); - assertTrue(id > 0); + assertEquals(100L, id); - // 验证数据库中是否已插入数据 - IncomeExpenseDetailsDO dbRecord = incomeExpenseDetailsMapper.selectById(id); - assertNotNull(dbRecord); - assertEquals("BUS20251215001", dbRecord.getBusinessNo()); - assertEquals("ORD20251215001", dbRecord.getOrderNo()); - assertEquals(1L, dbRecord.getOrganId()); - assertEquals(100L, dbRecord.getPurchaseId()); - assertEquals(1, dbRecord.getTradeType()); - assertEquals(2, dbRecord.getIncomeExpenseType()); - assertEquals(new BigDecimal("100.00"), dbRecord.getAmount()); - assertEquals(1, dbRecord.getCurrency()); - assertEquals("CNY", dbRecord.getCurrencyUnit()); - assertEquals("测试收支明细", dbRecord.getRemark()); + verify(incomeExpenseDetailsMapper, times(1)) + .insert(any(IncomeExpenseDetailsDO.class)); } } \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImplTest.java index 98286b158..265b7906e 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImplTest.java @@ -1,14 +1,18 @@ package com.cf.imes.module.system.service.funds.invoice; import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.cf.imes.framework.common.exception.ServiceException; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants; import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.framework.security.test.WithMockLoginUser; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.infra.api.file.FileApi; +import com.cf.imes.module.system.common.WithMockLoginUserExtension; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.*; import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceRecordsDO; import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceTitleInfoDO; @@ -22,13 +26,15 @@ import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum; import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum; import com.cf.imes.module.system.enums.pay.TradeTypeEnum; import com.cf.imes.module.system.service.organ.OrganService; -import jakarta.annotation.Resource; +import org.apache.ibatis.builder.MapperBuilderAssistant; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.bean.override.mockito.MockitoBean; -import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; @@ -39,7 +45,13 @@ import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** @@ -48,31 +60,35 @@ import static org.mockito.Mockito.when; * @author Gqr * @since 2025/12/15 15:31 */ -@Import(InvoiceServiceImpl.class) -class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { +@ExtendWith(WithMockLoginUserExtension.class) +class InvoiceServiceImplTest extends BaseMockitoUnitTest { - @Resource + @InjectMocks private InvoiceServiceImpl invoiceService; - @Resource + @Mock private InvoiceTitleInfoMapper invoiceTitleInfoMapper; - @Resource + @Mock private PurchaseRecordMapper purchaseRecordMapper; - @Resource + @Mock private InvoiceRecordsMapper invoiceRecordsMapper; - @MockitoBean + @Mock private OrganService organService; - @MockitoBean + @Mock private FileApi fileApi; + @BeforeAll + static void init(){ + TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), PurchaseRecordDO.class); + } + @Test @WithMockLoginUser void testGetInvoiceTitle() { - // 准备参数 Long organId = SecurityFrameworkUtils.getUserOrganId(); // 使用真实数据查询发票抬头信息 @@ -81,8 +97,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setOrganId(organId); o.setInvoiceTitle("测试公司"); }); - - invoiceTitleInfoMapper.insert(invoiceTitleInfoDO); + when(invoiceTitleInfoMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(invoiceTitleInfoDO); // 调用 InvoiceTitleInfo result = invoiceService.getInvoiceTitle(); @@ -92,6 +107,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { assertEquals(1L, result.getId()); assertEquals("测试公司", result.getInvoiceTitle()); assertEquals(organId, result.getOrganId()); + } @Test @@ -106,17 +122,32 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setTaxNumber("91330101MA2HXXXXXX"); reqVO.setEmail("test@company.com"); + // 内部校验 + when(invoiceTitleInfoMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(null); + invoiceService.insetInvoiceTitle(reqVO); - // ====== 校验数据库 ====== - InvoiceTitleInfoDO dbRecord = invoiceTitleInfoMapper.selectOne( - new LambdaQueryWrapper() - .eq(InvoiceTitleInfoDO::getOrganId, organId) - ); + // 不走更新 + verify(invoiceTitleInfoMapper, never()).updateById(any(InvoiceTitleInfoDO.class)); - assertNotNull(dbRecord); - assertEquals("测试公司", dbRecord.getInvoiceTitle()); - assertEquals("91330101MA2HXXXXXX", dbRecord.getTaxNumber()); + // 校验新增 + ArgumentCaptor captor = + ArgumentCaptor.forClass(InvoiceTitleInfoDO.class); + + verify(invoiceTitleInfoMapper).insert(captor.capture()); + + InvoiceTitleInfoDO inserted = captor.getValue(); + + assertEquals(organId, inserted.getOrganId()); + assertEquals(reqVO.getInvoiceTitle(), inserted.getInvoiceTitle()); + assertEquals(reqVO.getInvoiceType(), inserted.getInvoiceType()); + assertEquals(reqVO.getIssueType(), inserted.getIssueType()); + assertEquals(reqVO.getTaxNumber(), inserted.getTaxNumber()); + assertEquals(reqVO.getBankName(), inserted.getBankName()); + assertEquals(reqVO.getBankAccount(), inserted.getBankAccount()); + assertEquals(reqVO.getRegisteredAddress(), inserted.getRegisteredAddress()); + assertEquals(reqVO.getFixedPhone(), inserted.getFixedPhone()); + assertEquals(reqVO.getEmail(), inserted.getEmail()); } @Test @@ -128,15 +159,11 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setInvoiceType(0); reqVO.setTaxNumber(null); - ServiceException ex = assertThrows( - ServiceException.class, - () -> invoiceService.insetInvoiceTitle(reqVO) - ); + assertServiceException(() -> invoiceService.insetInvoiceTitle(reqVO), INVOICE_TITLE_ENTERPRISE_TAXNUMBER_EMPTY_ERROR); + + // 校验未调用 + verify(invoiceTitleInfoMapper, never()).selectOne(any(LambdaQueryWrapper.class)); - assertEquals( - INVOICE_TITLE_ENTERPRISE_TAXNUMBER_EMPTY_ERROR.getCode(), - ex.getCode() - ); } @Test @@ -144,7 +171,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { void insetInvoiceTitle_sameOrgan_throwOrgExists() { Long organId = SecurityFrameworkUtils.getUserOrganId(); - invoiceTitleInfoMapper.insert(InvoiceTitleInfoDO.builder() + when(invoiceTitleInfoMapper.selectOne(any())).thenReturn(InvoiceTitleInfoDO.builder() .organId(organId) .issueType(InvoiceIssueTypeEnum.PERSONAL.getValue()) .invoiceTitle("已存在") @@ -154,15 +181,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setInvoiceTitle("新抬头"); reqVO.setIssueType(InvoiceIssueTypeEnum.PERSONAL.getValue()); - ServiceException ex = assertThrows( - ServiceException.class, - () -> invoiceService.insetInvoiceTitle(reqVO) - ); - - assertEquals( - INVOICE_TITLE_ORG_EXISTS_ERROR.getCode(), - ex.getCode() - ); + assertServiceException(() -> invoiceService.insetInvoiceTitle(reqVO), INVOICE_TITLE_ORG_EXISTS_ERROR); } @Test @@ -173,41 +192,26 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setInvoiceTitle("测试抬头"); reqVO.setIssueType(InvoiceIssueTypeEnum.PERSONAL.getValue()); - ServiceException ex = assertThrows( - ServiceException.class, - () -> invoiceService.insetInvoiceTitle(reqVO) - ); - - assertEquals( - INVOICE_TITLE_NOT_EXISTS_ERROR.getCode(), - ex.getCode() - ); + assertServiceException(() -> invoiceService.insetInvoiceTitle(reqVO), INVOICE_TITLE_NOT_EXISTS_ERROR); } @Test @WithMockLoginUser void insetInvoiceTitle_update_orgNotMatch_throwException() { InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder() + .id(100L) .organId(2L) .issueType(InvoiceIssueTypeEnum.PERSONAL.getValue()) .invoiceTitle("原抬头") .build(); - invoiceTitleInfoMapper.insert(exist); + when(invoiceTitleInfoMapper.selectById(any())).thenReturn(exist); InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO(); reqVO.setId(exist.getId()); reqVO.setInvoiceTitle("非法更新"); reqVO.setIssueType(exist.getIssueType()); - ServiceException ex = assertThrows( - ServiceException.class, - () -> invoiceService.insetInvoiceTitle(reqVO) - ); - - assertEquals( - INVOICE_TITLE_NOT_EXISTS_ERROR.getCode(), - ex.getCode() - ); + assertServiceException(() -> invoiceService.insetInvoiceTitle(reqVO), INVOICE_TITLE_NOT_EXISTS_ERROR); } @Test @@ -223,26 +227,26 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { invoiceService.insetInvoiceTitle(reqVO); - // 验证数据库 - List list = invoiceTitleInfoMapper.selectList(null); - assertEquals(1, list.size()); - - InvoiceTitleInfoDO saved = list.get(0); - assertEquals(organId, saved.getOrganId()); - assertEquals("新增抬头", saved.getInvoiceTitle()); + // 验证插入 + verify(invoiceTitleInfoMapper).insert(argThat((InvoiceTitleInfoDO infoDO) -> + infoDO.getInvoiceTitle().equals(reqVO.getInvoiceTitle()) + && infoDO.getOrganId().equals(organId) + && infoDO.getIssueType().equals(reqVO.getIssueType()) + && infoDO.getInvoiceType().equals(reqVO.getInvoiceType()) + && infoDO.getEmail().equals(reqVO.getEmail()) + )); } @Test @WithMockLoginUser void insetInvoiceTitle_enterprise_taxNumberExists_throwException() { - // 先插入一条企业发票抬头 - InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder() + + when(invoiceTitleInfoMapper.selectOne(any())).thenReturn(null).thenReturn(InvoiceTitleInfoDO.builder() .organId(2L) // 不同组织也没关系 .invoiceTitle("已存在抬头") .issueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue()) .taxNumber("91330100XXXXXX") - .build(); - invoiceTitleInfoMapper.insert(exist); + .build()); // 再新增一条相同税号 InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO(); @@ -250,15 +254,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setIssueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue()); reqVO.setTaxNumber("91330100XXXXXX"); - ServiceException ex = assertThrows( - ServiceException.class, - () -> invoiceService.insetInvoiceTitle(reqVO) - ); - - assertEquals( - INVOICE_TITLE_TAXPAYERID_EXISTS_ERROR.getCode(), - ex.getCode() - ); + assertServiceException(() -> invoiceService.insetInvoiceTitle(reqVO), INVOICE_TITLE_TAXPAYERID_EXISTS_ERROR); } @Test @@ -266,13 +262,13 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { void insetInvoiceTitle_update_success() { Long organId = SecurityFrameworkUtils.getUserOrganId(); - // given:数据库已有数据(organId 一定要一致) InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder() + .id(100L) .organId(organId) .invoiceTitle("旧抬头") .issueType(InvoiceIssueTypeEnum.PERSONAL.getValue()) .build(); - invoiceTitleInfoMapper.insert(exist); + when(invoiceTitleInfoMapper.selectById(exist.getId())).thenReturn(exist); // when:更新 InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO(); @@ -282,17 +278,26 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { invoiceService.insetInvoiceTitle(reqVO); - // then:断言更新成功 - InvoiceTitleInfoDO updated = invoiceTitleInfoMapper.selectById(exist.getId()); - assertEquals("新抬头", updated.getInvoiceTitle()); + // 捕获 update 的参数,断言字段 + ArgumentCaptor captor = + ArgumentCaptor.forClass(InvoiceTitleInfoDO.class); + verify(invoiceTitleInfoMapper).updateById(captor.capture()); + + InvoiceTitleInfoDO actual = captor.getValue(); + + assertEquals(reqVO.getId(), actual.getId()); + assertEquals(reqVO.getInvoiceTitle(), actual.getInvoiceTitle()); + assertEquals(reqVO.getIssueType(), actual.getIssueType()); + } @Test - @WithMockLoginUser void getAvailablePage_whenEmptyList_returnEmptyPageResult() { // given InvoiceAmountAndAvailablePageReqVO reqVO = new InvoiceAmountAndAvailablePageReqVO(); + when(purchaseRecordMapper.selectPage(any(InvoiceAmountAndAvailablePageReqVO.class))).thenReturn(new PageResult()); + // when PageResult result = invoiceService.getAvailablePage(reqVO); @@ -304,7 +309,6 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - @WithMockLoginUser(organId = 1L) void getAvailablePage_whenHasData_returnConvertedPage() { // given InvoiceAmountAndAvailablePageReqVO reqVO = @@ -321,7 +325,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); o.setOrganId(1L); }); - purchaseRecordMapper.insert(invoiceRecordsDO); + when(purchaseRecordMapper.selectPage(any(InvoiceAmountAndAvailablePageReqVO.class))).thenReturn(new PageResult(List.of(invoiceRecordsDO), 1L)); // when PageResult result = @@ -364,7 +368,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { .issueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue()) .taxNumber("91330100XXXXXX") .build(); - invoiceTitleInfoMapper.insert(exist); + when(invoiceTitleInfoMapper.selectOne(any())).thenReturn(exist); InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO(); @@ -379,24 +383,28 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); o.setOrganId(1L); }); - purchaseRecordMapper.insert(invoiceRecordsDO); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(invoiceRecordsDO)); + // 有不可开票状态的记录 reqVO.setPurchaseRecordId(List.of(invoiceRecordsDO.getId())); assertServiceException(() -> invoiceService.applyInvoice(reqVO), INVOICE_APPLY_UNINVOICEABLE_EXIST); // 可开金额为0 - invoiceRecordsDO.setId(null); invoiceRecordsDO.setExternalSpent(BigDecimal.ZERO); invoiceRecordsDO.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); - purchaseRecordMapper.insert(invoiceRecordsDO); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(invoiceRecordsDO)); + reqVO.setPurchaseRecordId(List.of(invoiceRecordsDO.getId())); + when(purchaseRecordMapper.getInvoicableAmount(anyLong(), anyList())).thenReturn(BigDecimal.ZERO); + assertServiceException(() -> invoiceService.applyInvoice(reqVO), INVOICE_AMOUNT_ZERO_ERROR); // 更新开票状态和开票id数量不匹配 - invoiceRecordsDO.setId(null); invoiceRecordsDO.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); invoiceRecordsDO.setExternalSpent(new BigDecimal("100")); - purchaseRecordMapper.insert(invoiceRecordsDO); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(invoiceRecordsDO)); + when(purchaseRecordMapper.getInvoicableAmount(anyLong(), anyList())).thenReturn(BigDecimal.ONE); + when(purchaseRecordMapper.update(any(LambdaUpdateWrapper.class))).thenReturn(10); reqVO.setPurchaseRecordId(List.of(invoiceRecordsDO.getId(), 999L)); assertServiceException( @@ -409,14 +417,18 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { @Test @WithMockLoginUser(organId = 1L) void applyInvoice_success() { + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + Long organId = loginUser.getOrganId(); + Long userId = loginUser.getId(); + // 先插入一条企业发票抬头 InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder() - .organId(1L) // 不同组织也没关系 + .organId(organId) // 不同组织也没关系 .invoiceTitle("已存在抬头") .issueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue()) .taxNumber("91330100XXXXXX") .build(); - invoiceTitleInfoMapper.insert(exist); + when(invoiceTitleInfoMapper.selectOne(any())).thenReturn(exist); InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO(); @@ -428,9 +440,11 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode()); o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); - o.setOrganId(1L); + o.setOrganId(organId); }); - purchaseRecordMapper.insert(invoiceRecordsDO); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(invoiceRecordsDO)); + when(purchaseRecordMapper.getInvoicableAmount(anyLong(), anyList())).thenReturn(BigDecimal.ONE); + when(purchaseRecordMapper.update(any(LambdaUpdateWrapper.class))).thenReturn(1); Long recordId = invoiceRecordsDO.getId(); reqVO.setPurchaseRecordId(List.of(recordId)); @@ -438,28 +452,30 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { // 组织 OrganizationDO org = new OrganizationDO(); org.setName("测试组织"); - org.setId(1L); + org.setId(organId); when(organService.validOrgan(1L)).thenReturn(org); assertDoesNotThrow(() -> { invoiceService.applyInvoice(reqVO); }); - List invoiceRecordsDOS = invoiceRecordsMapper.selectList(); - assertEquals(1, invoiceRecordsDOS.size()); - InvoiceRecordsDO query = invoiceRecordsDOS.get(0); - assertNotNull(invoiceRecordsDO); - assertEquals(invoiceRecordsDO.getOrganId(), invoiceRecordsDO.getOrganId()); - assertEquals(query.getPurchaseIds(), List.of(invoiceRecordsDO.getId()).toString()); - assertEquals("测试组织", query.getOrganName()); + + // 验证插入 + verify(invoiceRecordsMapper).insert(argThat((InvoiceRecordsDO recordsDO) -> + recordsDO.getOrganId().equals(organId) + && recordsDO.getUserId().equals(userId) + && recordsDO.getOrganName().equals("测试组织") + && recordsDO.getInvoiceAmount().equals(BigDecimal.ONE) + && recordsDO.getStatus().equals(InvoiceStatusEnum.PENDINGINVOICING.getCode()) + )); } @Test - @WithMockLoginUser void getInvoiceRecords_whenEmptyList_returnEmptyPageResult() { // given InvoiceDetailsPageReqVO pageReqVO = new InvoiceDetailsPageReqVO(); // when + when(invoiceRecordsMapper.selectInvoiceRecordsPage(any())).thenReturn(new PageResult<>()); PageResult result = invoiceService.getInvoiceRecords(pageReqVO); // then @@ -469,7 +485,6 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - @WithMockLoginUser void getInvoiceRecords_whenHasData_returnConvertedPage() { // given InvoiceDetailsPageReqVO pageReqVO = new InvoiceDetailsPageReqVO(); @@ -479,7 +494,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInvoiceAmount(new BigDecimal("100.00")); o.setStatus(InvoiceStatusEnum.INVOICABLE.getCode()); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectInvoiceRecordsPage(any())).thenReturn(new PageResult<>(List.of(invoiceRecordsDO), 1L)); // when PageResult result = invoiceService.getInvoiceRecords(pageReqVO); @@ -496,13 +511,11 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - @WithMockLoginUser void getInvoiceRecordDetail_whenRecordNotExists_thenThrowException() { assertServiceException(() -> invoiceService.getInvoiceRecordDetail(1L), INVOICE_NO_EXIST); } @Test - @WithMockLoginUser void getInvoiceRecordDetail_whenRecordExists_thenReturnDetail() { // 准备数据 InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> { @@ -512,7 +525,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setPurchaseIds("[1, 2]"); o.setInvoiceTitleInfo(zipString("{\"invoiceTitle\":\"测试公司\"}")); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(anyLong())).thenReturn(invoiceRecordsDO); PurchaseRecordDO purchase1 = randomPojo(PurchaseRecordDO.class, o -> { o.setId(1L); @@ -523,7 +536,6 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); }); - purchaseRecordMapper.insert(purchase1); PurchaseRecordDO purchase2 = randomPojo(PurchaseRecordDO.class, o -> { o.setId(2L); @@ -534,7 +546,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); }); - purchaseRecordMapper.insert(purchase2); + when(purchaseRecordMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(List.of(purchase1, purchase2)); // 调用方法 InvoiceDetailsRespVO result = invoiceService.getInvoiceRecordDetail(1L); @@ -567,7 +579,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setId(1L); o.setStatus(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode()); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -583,7 +595,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setId(1L); o.setStatus(InvoiceStatusEnum.INVOICINGFAILED.getCode()); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -602,7 +614,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInvoiceTitleId(1L); o.setOrganId(1L); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -621,14 +633,14 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInvoiceTitleId(1L); o.setOrganId(1L); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> { o.setId(1L); o.setOrganId(1L); o.setInvoiceTitle("测试公司"); }); - invoiceTitleInfoMapper.insert(title); + when(invoiceTitleInfoMapper.selectById(anyLong())).thenReturn(title); PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> { o.setId(1L); @@ -637,7 +649,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); }); - purchaseRecordMapper.insert(purchase); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(purchase)); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -657,14 +669,14 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInvoiceTitleId(1L); o.setOrganId(1L); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> { o.setId(1L); o.setOrganId(1L); o.setInvoiceTitle("测试公司"); }); - invoiceTitleInfoMapper.insert(title); + when(invoiceTitleInfoMapper.selectById(anyLong())).thenReturn(title); PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> { o.setId(1L); @@ -673,7 +685,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); }); - purchaseRecordMapper.insert(purchase); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(purchase)); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -695,14 +707,14 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setOrganId(1L); o.setInvoiceAmount(new BigDecimal("100.00")); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> { o.setId(1L); o.setOrganId(1L); o.setInvoiceTitle("测试公司"); }); - invoiceTitleInfoMapper.insert(title); + when(invoiceTitleInfoMapper.selectById(anyLong())).thenReturn(title); PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> { o.setId(1L); @@ -711,11 +723,12 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); }); - purchaseRecordMapper.insert(purchase); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(purchase)); // Mock 文件上传 + Long fileId = 999L; MockMultipartFile file = new MockMultipartFile("file", "测试公司-20231010101010-100.pdf", "application/pdf", "content".getBytes()); - when(fileApi.createFileAndReturnId(any(byte[].class), anyString())).thenReturn(1L); + when(fileApi.createFileAndReturnId(any(byte[].class), anyString())).thenReturn(fileId); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -727,17 +740,15 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { assertDoesNotThrow(() -> invoiceService.confirmInvoice(reqVO, file)); // 验证数据库更新 - InvoiceRecordsDO updatedRecord = invoiceRecordsMapper.selectById(1L); - assertEquals(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode(), updatedRecord.getStatus()); - assertEquals("FP20231010101010", updatedRecord.getInvoiceNo()); - assertEquals("同意开票", updatedRecord.getRemark()); - assertEquals("测试用户", updatedRecord.getInvoicePerson()); - assertEquals(1L, updatedRecord.getInvoicePersonId()); - assertNotNull(updatedRecord.getInvoiceTime()); - assertEquals(1L, updatedRecord.getInvoiceAttachmentId()); + verify(invoiceRecordsMapper).updateById(argThat((InvoiceRecordsDO recordsDO) -> + recordsDO.getStatus().equals(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode()) + && recordsDO.getRemark().equals(reqVO.getRemark()) + && recordsDO.getInvoiceAttachmentId().equals(fileId) + && recordsDO.getInvoiceNo().equals(reqVO.getInvoiceNo()) + )); - PurchaseRecordDO updatedPurchase = purchaseRecordMapper.selectById(1L); - assertEquals(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode(), updatedPurchase.getIsInvocing()); + verify(purchaseRecordMapper, times(1)) + .updateBatch(anyList()); } @Test @@ -751,14 +762,14 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setInvoiceTitleId(1L); o.setOrganId(1L); }); - invoiceRecordsMapper.insert(invoiceRecordsDO); + when(invoiceRecordsMapper.selectById(1L)).thenReturn(invoiceRecordsDO); InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> { o.setId(1L); o.setOrganId(1L); o.setInvoiceTitle("测试公司"); }); - invoiceTitleInfoMapper.insert(title); + when(invoiceTitleInfoMapper.selectById(anyLong())).thenReturn(title); PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> { o.setId(1L); @@ -767,7 +778,7 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); o.setInitial(false); }); - purchaseRecordMapper.insert(purchase); + when(purchaseRecordMapper.selectByIds(anyList())).thenReturn(List.of(purchase)); InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO(); reqVO.setId(1L); @@ -778,96 +789,49 @@ class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest { assertDoesNotThrow(() -> invoiceService.confirmInvoice(reqVO, null)); // 验证数据库更新 - InvoiceRecordsDO updatedRecord = invoiceRecordsMapper.selectById(1L); - assertEquals(InvoiceStatusEnum.INVOICINGFAILED.getCode(), updatedRecord.getStatus()); - assertEquals("拒绝开票", updatedRecord.getRemark()); - assertEquals("测试用户", updatedRecord.getInvoicePerson()); - assertEquals(1L, updatedRecord.getInvoicePersonId()); - assertNotNull(updatedRecord.getInvoiceTime()); + verify(invoiceRecordsMapper).updateById(argThat((InvoiceRecordsDO recordsDO) -> + recordsDO.getStatus().equals(InvoiceStatusEnum.INVOICINGFAILED.getCode()) + && recordsDO.getRemark().equals(reqVO.getRemark()) + )); - PurchaseRecordDO updatedPurchase = purchaseRecordMapper.selectById(1L); - assertEquals(InvoiceStatusEnum.INVOICABLE.getCode(), updatedPurchase.getIsInvocing()); + verify(purchaseRecordMapper, times(1)) + .updateBatch(anyList()); } @Test @WithMockLoginUser void getInvoiceAmount_whenNoData_thenReturnZeroValues() { + InvoiceAmountRespVO invoiceAmountRespVO = new InvoiceAmountRespVO(); + invoiceAmountRespVO.setInvocable(BigDecimal.ZERO); + invoiceAmountRespVO.setInTheInvoice(BigDecimal.ONE); + invoiceAmountRespVO.setInvoiced(BigDecimal.TEN); + when(purchaseRecordMapper.getOrgInvoiceAmountStatistics(anyLong())).thenReturn(invoiceAmountRespVO); + // 调用方法 InvoiceAmountRespVO result = invoiceService.getInvoiceAmount(); // 验证结果 assertNotNull(result); assertEquals(BigDecimal.ZERO, result.getInvocable()); - assertEquals(BigDecimal.ZERO, result.getInTheInvoice()); - assertEquals(BigDecimal.ZERO, result.getInvoiced()); + assertEquals(BigDecimal.ONE, result.getInTheInvoice()); + assertEquals(BigDecimal.TEN, result.getInvoiced()); } - - @Test - @WithMockLoginUser - void getInvoiceAmount_whenHasData_thenReturnCorrectValues() { - // 可开票 - PurchaseRecordDO purchaseRecordDO = randomPojo(PurchaseRecordDO.class, o->{ - o.setExternalSpent(new BigDecimal("100.00")); - o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode()); - o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode()); - o.setInitial(false); - o.setOrganId(SecurityFrameworkUtils.getUserOrganId()); - }); - purchaseRecordMapper.insert(purchaseRecordDO); - - InvoiceAmountRespVO result = invoiceService.getInvoiceAmount(); - assertNotNull(result); - assertEquals(new BigDecimal("100.00"), result.getInvocable()); - - // 开票中 - purchaseRecordDO.setId(null); - purchaseRecordDO.setIsInvocing(InvoiceStatusEnum.PENDINGINVOICING.getCode()); - purchaseRecordMapper.insert(purchaseRecordDO); - result = invoiceService.getInvoiceAmount(); - assertNotNull(result); - assertEquals(new BigDecimal("100.00"), result.getInTheInvoice()); - - // 已开票 - purchaseRecordDO.setId(null); - purchaseRecordDO.setIsInvocing(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode()); - purchaseRecordMapper.insert(purchaseRecordDO); - result = invoiceService.getInvoiceAmount(); - assertNotNull(result); - assertEquals(new BigDecimal("100.00"), result.getInvoiced()); - } - @Test void getManageInvoiceAmount_whenNoData_thenReturnZeroValues() { + InvoiceAmountRespVO invoiceAmountRespVO = new InvoiceAmountRespVO(); + invoiceAmountRespVO.setPendingInvoice(BigDecimal.TEN); + invoiceAmountRespVO.setInvoiced(BigDecimal.ZERO); + when(invoiceRecordsMapper.getManageInvoiceAmountStatistics()).thenReturn(invoiceAmountRespVO); + // 调用方法 InvoiceAmountRespVO result = invoiceService.getManageInvoiceAmount(); // 验证结果 assertNotNull(result); - assertEquals(BigDecimal.ZERO, result.getPendingInvoice()); + assertEquals(BigDecimal.TEN, result.getPendingInvoice()); assertEquals(BigDecimal.ZERO, result.getInvoiced()); } - @Test - void getManageInvoiceAmount_whenHasData_thenReturnCorrectValues() { - // 待开票 - InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> { - o.setInvoiceAmount(new BigDecimal("150.00")); - o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode()); - }); - invoiceRecordsMapper.insert(invoiceRecordsDO); - InvoiceAmountRespVO result = invoiceService.getManageInvoiceAmount(); - assertNotNull(result); - assertEquals(new BigDecimal("150.00"), result.getPendingInvoice()); - - // 已开票 - invoiceRecordsDO.setId(null); - invoiceRecordsDO.setStatus(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode()); - invoiceRecordsDO.setInvoiceAmount(new BigDecimal("300.00")); - invoiceRecordsMapper.insert(invoiceRecordsDO); - result = invoiceService.getManageInvoiceAmount(); - assertEquals(new BigDecimal("300.00"), result.getInvoiced()); - } - @Test void getFileExtension_whenFileNameIsNull_thenReturnEmpty() { assertEquals("", InvoiceServiceImpl.getFileExtension(null)); diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImplTest.java index a6e5362d6..5ac01b470 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImplTest.java @@ -3,31 +3,31 @@ package com.cf.imes.module.system.service.funds.organamount; import com.cf.imes.framework.common.enums.StatisticsUnit; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.framework.security.test.WithMockLoginUser; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; +import com.cf.imes.module.system.common.WithMockLoginUserExtension; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.ManageAmountOverviewRespVO; +import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountGroupByCreateTimeRespVO; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganFundsStatisticsReqVO; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganProductOverviewRespVO; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.OrgEarliestPurchaseProductRespVO; import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; -import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO; import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper; import com.cf.imes.module.system.service.funds.invoice.InvoiceService; import com.cf.imes.module.system.service.funds.purchase.PurchaseService; import com.cf.imes.module.system.service.organ.OrganService; -import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -35,27 +35,21 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -/** - * - * - * @author Gqr - * @since 2025/12/31 14:00 - */ -@Import(OrganAmountServiceImpl.class) -public class OrganAmountServiceImplTest extends BaseDbAndRedisUnitTest { - @Resource +@ExtendWith(WithMockLoginUserExtension.class) +class OrganAmountServiceImplTest extends BaseMockitoUnitTest { + @Mock IncomeExpenseDetailsMapper incomeExpenseDetailsMapper; - @Resource + @InjectMocks private OrganAmountServiceImpl organAmountService; - @MockitoBean + @Mock private OrganService organService; - @MockitoBean + @Mock private PurchaseService purchaseService; - @MockitoBean + @Mock private InvoiceService invoiceService; @Test @@ -64,13 +58,13 @@ public class OrganAmountServiceImplTest extends BaseDbAndRedisUnitTest { // ===== given ===== Long organId = SecurityFrameworkUtils.getUserOrganId(); - PurchaseRecordDO record = new PurchaseRecordDO(); - record.setEndTime(LocalDate.of(2025, 12, 31)); - record.setInitial(false); - record.setPurchaseDuration(12); - record.setPurchaseDurationUnit(1); + PurchaseRecordDO recordDO = new PurchaseRecordDO(); + recordDO.setEndTime(LocalDate.of(2025, 12, 31)); + recordDO.setInitial(false); + recordDO.setPurchaseDuration(12); + recordDO.setPurchaseDurationUnit(1); - OrgEarliestPurchaseProductRespVO resp = new OrgEarliestPurchaseProductRespVO(record); + OrgEarliestPurchaseProductRespVO resp = new OrgEarliestPurchaseProductRespVO(recordDO); when(purchaseService.getOrgEarliestProductDetail(organId)) .thenReturn(resp); @@ -125,11 +119,11 @@ public class OrganAmountServiceImplTest extends BaseDbAndRedisUnitTest { void testGetOrganProductOverview_initialPurchase() { Long organId = SecurityFrameworkUtils.getUserOrganId(); - PurchaseRecordDO record = new PurchaseRecordDO(); - record.setEndTime(LocalDate.of(2025, 1, 1)); - record.setInitial(true); + PurchaseRecordDO recordDO = new PurchaseRecordDO(); + recordDO.setEndTime(LocalDate.of(2025, 1, 1)); + recordDO.setInitial(true); - OrgEarliestPurchaseProductRespVO resp = new OrgEarliestPurchaseProductRespVO(record); + OrgEarliestPurchaseProductRespVO resp = new OrgEarliestPurchaseProductRespVO(recordDO); when(purchaseService.getOrgEarliestProductDetail(organId)) .thenReturn(resp); @@ -181,24 +175,23 @@ public class OrganAmountServiceImplTest extends BaseDbAndRedisUnitTest { LocalDate.now().plusDays(1) }); - IncomeExpenseDetailsDO pojo1 = randomPojo(IncomeExpenseDetailsDO.class, o -> { - o.setOrganId(organId); - o.setAmount(new BigDecimal("100")); - o.setCreateTime(LocalDateTime.now().minusDays(2)); - }); - IncomeExpenseDetailsDO pojo2 = randomPojo(IncomeExpenseDetailsDO.class, o -> { - o.setOrganId(organId); - o.setAmount(new BigDecimal("200")); - o.setCreateTime(LocalDateTime.now()); - }); - IncomeExpenseDetailsDO pojo3 = randomPojo(IncomeExpenseDetailsDO.class, o -> { - o.setAmount(new BigDecimal("200")); - o.setCreateTime(LocalDateTime.now()); - }); + OrganAmountGroupByCreateTimeRespVO vo1 = new OrganAmountGroupByCreateTimeRespVO(); + vo1.setDate("2026-1-14"); + vo1.setAmount(new BigDecimal("100")); - incomeExpenseDetailsMapper.insert(pojo1); - incomeExpenseDetailsMapper.insert(pojo2); - incomeExpenseDetailsMapper.insert(pojo3); + OrganAmountGroupByCreateTimeRespVO vo2 = new OrganAmountGroupByCreateTimeRespVO(); + vo2.setDate("2026-1-16"); + vo2.setAmount(new BigDecimal("200")); + + OrganAmountGroupByCreateTimeRespVO vo3 = new OrganAmountGroupByCreateTimeRespVO(); + vo3.setDate("2026-1-15"); + vo3.setAmount(new BigDecimal("200")); + + List organAmountGroupByCreateTimeRespVOS = new ArrayList<>(); + organAmountGroupByCreateTimeRespVOS.add(vo1); + organAmountGroupByCreateTimeRespVOS.add(vo2); + + when(incomeExpenseDetailsMapper.selectOrganIncomeExpenseTrendGroupByCreateTime(reqVO, organId)).thenReturn(organAmountGroupByCreateTimeRespVOS); // when query org Map result = @@ -215,14 +208,16 @@ public class OrganAmountServiceImplTest extends BaseDbAndRedisUnitTest { assertArrayEquals( new BigDecimal[]{ - new BigDecimal("100.00"), + new BigDecimal("100"), BigDecimal.ZERO, - new BigDecimal("200.00"), + new BigDecimal("200"), BigDecimal.ZERO, }, data ); + organAmountGroupByCreateTimeRespVOS.add(vo3); + when(incomeExpenseDetailsMapper.selectOrganIncomeExpenseTrendGroupByCreateTime(reqVO, null)).thenReturn(organAmountGroupByCreateTimeRespVOS); // when not query org result = organAmountService.getConsumptionTrend(reqVO, false); @@ -237,9 +232,9 @@ public class OrganAmountServiceImplTest extends BaseDbAndRedisUnitTest { assertArrayEquals( new BigDecimal[]{ - new BigDecimal("100.00"), - BigDecimal.ZERO, - new BigDecimal("400.00"), + new BigDecimal("100"), + new BigDecimal("200"), + new BigDecimal("200"), BigDecimal.ZERO, }, data diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/productpromotion/ProductPromotionServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/productpromotion/ProductPromotionServiceImplTest.java index a75337c3d..2c59536a1 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/productpromotion/ProductPromotionServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/productpromotion/ProductPromotionServiceImplTest.java @@ -1,9 +1,12 @@ package com.cf.imes.module.system.service.funds.productpromotion; -import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils; -import com.cf.imes.framework.test.core.ut.BaseDbClearAfterClassAndRedisUnitTest; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO; import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionSaveReqVO; import com.cf.imes.module.system.dal.dataobject.funds.productpromotion.ProductPromotionDO; @@ -11,18 +14,15 @@ import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import com.cf.imes.module.system.dal.mysql.funds.productpromotion.ProductPromotionMapper; import com.cf.imes.module.system.enums.pay.DurationUnitEnum; import com.cf.imes.module.system.service.funds.products.ProductsDetailService; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; +import org.apache.ibatis.builder.MapperBuilderAssistant; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.time.LocalDateTime; import java.util.List; -import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals; import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException; import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; @@ -33,34 +33,35 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -/** - * @author Gqr - * @since 2025/10/24 11:20 - */ -@Import(ProductPromotionServiceImpl.class) -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitTest { - @Resource + +class ProductPromotionServiceImplTest extends BaseMockitoUnitTest { + @InjectMocks private ProductPromotionServiceImpl productPromotionService; - @Resource + @Mock private ProductPromotionMapper productPromotionMapper; - @MockitoBean + @Mock private ProductsDetailService productsDetailService; - @MockitoBean + @Mock private I18nUtils i18nUtils; - private static ProductPromotionDO createDO; + @BeforeAll + static void init(){ + TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), ProductPromotionDO.class); + } @Test - @Order(1) void testCreate() { ProductPromotionSaveReqVO reqVO = randomPojo(ProductPromotionSaveReqVO.class, o -> { - o.setId(null); + o.setId(100L); o.setActivityName("充值送活动"); o.setPurchaseDuration(1); o.setPurchaseDurationUnit(DurationUnitEnum.YEAR.getCode()); @@ -76,27 +77,33 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT productsDO.setProductName("产品名称"); when(productsDetailService.validateProductExist(any())).thenReturn(productsDO); - Long id = productPromotionService.create(reqVO); + productPromotionService.create(reqVO); // 校验数据库插入结果 - createDO = productPromotionMapper.selectById(id); - assertNotNull(createDO); - assertEquals("充值送活动", createDO.getActivityName()); - assertEquals(1, createDO.getPurchaseDuration()); - assertEquals(DurationUnitEnum.YEAR.getCode(), createDO.getPurchaseDurationUnit()); - assertEquals(1, createDO.getGiftDuration()); - assertEquals(DurationUnitEnum.DAY.getCode(), createDO.getGiftDurationUnit()); + // 验证插入 + verify(productPromotionMapper).insert(argThat((ProductPromotionDO infoDO) -> + infoDO.getProductId().equals(productsDO.getId()) + && infoDO.getProductName().equals(productsDO.getProductName()) + && infoDO.getId().equals(100L) + && infoDO.getActivityName().equals(reqVO.getActivityName()) + && infoDO.getPurchaseDuration().equals(reqVO.getPurchaseDuration()) + && infoDO.getPurchaseDurationUnit().equals(reqVO.getPurchaseDurationUnit()) + && infoDO.getGiftDuration().equals(reqVO.getGiftDuration()) + && infoDO.getGiftDurationUnit().equals(reqVO.getGiftDurationUnit()) + )); // 再次插入相同活动名称,断言异常 + when(productPromotionMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(new ProductPromotionDO()); assertServiceException(() -> productPromotionService.create(reqVO), PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST); // 再次插入相同产品-相同购买时长和单位,断言异常 reqVO.setActivityName("充值送活动1"); + when(productPromotionMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(null).thenReturn(new ProductPromotionDO()); + when(i18nUtils.getMessage(anyString())).thenReturn("年"); assertServiceException(() -> productPromotionService.create(reqVO), PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, reqVO.getPurchaseDuration(), DurationUnitEnum.getDesc(reqVO.getPurchaseDurationUnit())); } @Test - @Order(2) void testUpdate_not_exist() { ProductPromotionSaveReqVO reqVO = new ProductPromotionSaveReqVO(); reqVO.setId(321L); @@ -111,50 +118,48 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT } @Test - @Order(3) void testUpdate() { - - // 插入 - ProductPromotionDO createDO1 = new ProductPromotionDO(); - createDO1.setId(null); - createDO1.setActivityName("充值送活动新"); - createDO1.setPurchaseDuration(1); - createDO1.setPurchaseDurationUnit(DurationUnitEnum.YEAR.getCode()); - createDO1.setProductId(2L); - createDO1.setProductName("产品名称2"); - createDO1.setGiftDuration(1); - createDO1.setGiftDurationUnit(DurationUnitEnum.DAY.getCode()); - createDO1.setStartTime(LocalDateTime.now()); - createDO1.setEndTime(LocalDateTime.now().plusDays(1)); - - productPromotionMapper.insert(createDO1); - ProductPromotionSaveReqVO reqVO = new ProductPromotionSaveReqVO(); - reqVO.setId(createDO1.getId()); + reqVO.setId(100L); reqVO.setActivityName("充值送活动"); - assertServiceException(() -> productPromotionService.update(reqVO), - PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST); + reqVO.setPurchaseDuration(1); + reqVO.setPurchaseDurationUnit(DurationUnitEnum.YEAR.getCode()); ProductsDO productsDO = new ProductsDO(); productsDO.setId(2L); productsDO.setProductName("产品名称2"); when(productsDetailService.validateProductExist(any())).thenReturn(productsDO); + // 再次插入相同活动名称,断言异常 + when(productPromotionMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(new ProductPromotionDO()).thenReturn(new ProductPromotionDO()); + assertServiceException(() -> productPromotionService.update(reqVO), PRODUCT_PROMOTION_ACTIVE_NAME_IS_EXIST); + + // 再次插入相同产品-相同购买时长和单位,断言异常 + reqVO.setActivityName("充值送活动1"); + when(productPromotionMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(new ProductPromotionDO()).thenReturn(null).thenReturn(new ProductPromotionDO()); + when(i18nUtils.getMessage(anyString())).thenReturn("年"); + assertServiceException(() -> productPromotionService.update(reqVO), PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, reqVO.getPurchaseDuration(), DurationUnitEnum.getDesc(reqVO.getPurchaseDurationUnit())); + // 更新成功 - ProductPromotionSaveReqVO update = BeanUtil.copyProperties(createDO1, ProductPromotionSaveReqVO.class); - assertDoesNotThrow(() -> productPromotionService.update(update)); + when(productPromotionMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(new ProductPromotionDO()).thenReturn(null).thenReturn(null); + productPromotionService.update(reqVO); + + // 验证数据库更新 + verify(productPromotionMapper).updateById(argThat((ProductPromotionDO productPromotionDO) -> + productPromotionDO.getProductId().equals(productsDO.getId()) + && productPromotionDO.getProductName().equals(productsDO.getProductName()) + && productPromotionDO.getId().equals(reqVO.getId()) + && productPromotionDO.getActivityName().equals(reqVO.getActivityName()) + )); } - @Test - @Order(3) void testGet_not_exist() { assertServiceException(() -> productPromotionService.get(null), PRODUCT_PROMOTION_NO_EXIST); } @Test - @Order(5) void testGetPage_success() { ProductPromotionDO detail = randomPojo(ProductPromotionDO.class, o -> { o.setId(null); @@ -166,23 +171,6 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT o.setRemark("晨丰备注1"); }); - productPromotionMapper.insert(detail); - - // 不匹配 ActivityName - productPromotionMapper.insert(cloneIgnoreId(detail, o -> o.setActivityName("新分页活动"))); - - // 不匹配 RechargeGiftType - productPromotionMapper.insert(cloneIgnoreId(detail, o -> o.setPurchaseDuration(4))); - - // 不匹配 GiftAmount - productPromotionMapper.insert(cloneIgnoreId(detail, o -> o.setGiftDuration(5))); - - // 不匹配 RechargeAmount - productPromotionMapper.insert(cloneIgnoreId(detail, o -> o.setRemark("晨丰备1注"))); - - // 被逻辑删除 - productPromotionMapper.insert(cloneIgnoreId(detail, o -> o.setDeleted(true))); - // ============ 构造查询参数 ============ ProductPromotionPageReqVO reqVO = new ProductPromotionPageReqVO(); reqVO.setActivityName("晨丰"); @@ -192,6 +180,8 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT reqVO.setPageNo(1); reqVO.setPageSize(10); + when(productPromotionMapper.selectPage(reqVO)).thenReturn(new PageResult<>(List.of(detail), 1L)); + // ============ 调用方法 ============ PageResult pageResult = productPromotionService.getPage(reqVO); @@ -202,27 +192,30 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT } @Test - @Order(6) void testDelete() { - assertDoesNotThrow(() -> productPromotionService.delete(createDO.getId())); + ProductPromotionDO exist = randomPojo(ProductPromotionDO.class); + + when(productPromotionMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(exist); + + assertDoesNotThrow(() -> productPromotionService.delete(exist.getId())); + + verify(productPromotionMapper, times(1)).deleteById(exist.getId()); } @Test - @Order(7) void testDelete_not_exist() { assertServiceException(() -> productPromotionService.delete(null), PRODUCT_PROMOTION_NO_EXIST); assertServiceException(() -> productPromotionService.delete(321L), PRODUCT_PROMOTION_NO_EXIST); } @Test - @Order(8) void testGetAvailableRechargeActiveList() { // 当前时间 LocalDateTime now = LocalDateTime.now(); Long productId = 1000L; - // 1️⃣ 有效活动(时间区间内) + // 有效活动(时间区间内) ProductPromotionDO valid = new ProductPromotionDO(); valid.setActivityName("有效活动"); valid.setProductId(productId); @@ -236,54 +229,25 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT valid.setDeleted(false); productPromotionMapper.insert(valid); - // 2️⃣ 未开始活动 - ProductPromotionDO notStarted = new ProductPromotionDO(); - notStarted.setActivityName("未开始活动"); - notStarted.setProductId(productId); - notStarted.setProductName("产品名称"); - notStarted.setPurchaseDuration(2); - notStarted.setPurchaseDurationUnit(DurationUnitEnum.YEAR.getCode()); - notStarted.setGiftDuration(2); - notStarted.setGiftDurationUnit(DurationUnitEnum.DAY.getCode()); - notStarted.setStartTime(now.plusDays(1)); - notStarted.setEndTime(now.plusDays(2)); - notStarted.setDeleted(false); - productPromotionMapper.insert(notStarted); - - // 3️⃣ 已过期活动 - ProductPromotionDO expired = new ProductPromotionDO(); - expired.setActivityName("已过期活动"); - expired.setProductId(productId); - expired.setProductName("产品名称"); - expired.setPurchaseDuration(3); - expired.setPurchaseDurationUnit(DurationUnitEnum.YEAR.getCode()); - expired.setGiftDuration(3); - expired.setGiftDurationUnit(DurationUnitEnum.DAY.getCode()); - expired.setStartTime(now.minusDays(5)); - expired.setEndTime(now.minusDays(1)); - expired.setDeleted(false); - productPromotionMapper.insert(expired); - - // 4️⃣ 被逻辑删除的活动 - ProductPromotionDO deleted = new ProductPromotionDO(); - deleted.setActivityName("被删除活动"); - deleted.setProductId(productId); - deleted.setProductName("产品名称"); - deleted.setPurchaseDuration(4); - deleted.setPurchaseDurationUnit(DurationUnitEnum.YEAR.getCode()); - deleted.setGiftDuration(4); - deleted.setGiftDurationUnit(DurationUnitEnum.DAY.getCode()); - deleted.setStartTime(now.minusDays(1)); - deleted.setEndTime(now.plusDays(1)); - deleted.setDeleted(true); - productPromotionMapper.insert(deleted); + when(productPromotionMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(List.of(valid)); // 执行被测方法 List result = productPromotionService.getAvailableProductPromotionList(productId); - // 验证结果 - assertEquals(1, result.size(), "只应返回一个有效活动"); - assertEquals("有效活动", result.get(0).getActivityName()); + // then + assertNotNull(result); + assertEquals(1L, result.size()); + + // 校验 查询条件 + verify(productPromotionMapper).selectList( + argThat((LambdaQueryWrapper wrapper) -> + wrapper.getSqlSegment().contains("deleted") + && wrapper.getSqlSegment().contains("product_id") + && wrapper.getSqlSegment().contains("start_time") + && wrapper.getSqlSegment().contains("end_time") + ) + ); + } } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImplTest.java index 065c6e00b..83560d242 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImplTest.java @@ -1,8 +1,12 @@ package com.cf.imes.module.system.service.funds.products; +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsSaveReqVO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; @@ -11,14 +15,15 @@ import com.cf.imes.module.system.dal.mysql.funds.products.ProductsDetailMapper; import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper; import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum; import com.cf.imes.module.system.enums.products.ProductStatusEnum; -import jakarta.annotation.Resource; +import org.apache.ibatis.builder.MapperBuilderAssistant; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.math.BigDecimal; +import java.util.List; -import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals; import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException; import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; @@ -31,26 +36,35 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * @author Gqr * @since 2025/10/14 13:48 */ -@Import(ProductsDetailServiceImpl.class) -public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { - @Resource +class ProductsDetailServiceImplTest extends BaseMockitoUnitTest { + @InjectMocks private ProductsDetailServiceImpl productsDetailService; - @Resource + @Mock private ProductsDetailMapper productsDetailMapper; - @MockitoBean + @Mock private ProductsMapper productsMapper; - @MockitoBean + @Mock private I18nUtils i18nUtils; + @BeforeAll + static void init(){ + TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), ProductsDetailDO.class); + } + @Test void testCreateProductDetails() { // mock下架状态的产品 @@ -62,16 +76,30 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { when(productsMapper.selectOne(any())).thenReturn(mockProduct); ProductDetailsSaveReqVO productDetailsSaveReqVO = randomPojo(ProductDetailsSaveReqVO.class, p -> { - p.setId(null); + p.setDiscount(BigDecimal.valueOf(10)); + p.setDuration(ProductDurationUnitEnum.YEAR.getCode()); + p.setProductId(mockProduct.getId()); }); + // 模拟 Mapper 插入时生成 ID + doAnswer(invocation -> { + ProductsDetailDO detail = invocation.getArgument(0); + detail.setId(100L); // 模拟自增主键 + return null; + }).when(productsDetailMapper).insert(any(ProductsDetailDO.class)); + // 调用 Long id = productsDetailService.create(productDetailsSaveReqVO); + // 断言 - assertNotNull(id); - // 校验记录的属性是否正确 - ProductsDetailDO productsDetailDO = productsDetailMapper.selectById(id); - assertPojoEquals(productDetailsSaveReqVO, productsDetailDO, "id"); + assertEquals(100L,id); + + // 验证 Mapper 方法被调用一次 + verify(productsDetailMapper, times(1)).insert(argThat((ProductsDetailDO detail) -> + detail.getDiscount().equals(productDetailsSaveReqVO.getDiscount()) + && detail.getDuration().equals(productDetailsSaveReqVO.getDuration()) + && detail.getProductId().equals(mockProduct.getId()) + )); } @Test @@ -99,20 +127,18 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { mockProduct.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); when(productsMapper.selectOne(any())).thenReturn(mockProduct); - // 插入一条与 createReqVO 冲突的数据 - ProductsDetailDO existing = new ProductsDetailDO(); - existing.setProductId(1L); - existing.setDuration(12); - existing.setDurationUnit(0); - existing.setDeleted(false); - productsDetailMapper.insert(existing); // 模拟新增同样 duration + unit 的记录 ProductDetailsSaveReqVO reqVO = new ProductDetailsSaveReqVO() - .setProductId(existing.getProductId()) - .setDuration(existing.getDuration()) - .setDurationUnit(existing.getDurationUnit()); + .setId(999L) + .setProductId(123L) + .setDuration(1) + .setDurationUnit(ProductDurationUnitEnum.MONTH.getCode()); + // mock重复存在 + when(productsDetailMapper.selectCountByDuration(reqVO.getProductId(), reqVO.getId(), reqVO.getDuration(), reqVO.getDurationUnit())).thenReturn(1); + + when(i18nUtils.getMessage(anyString())).thenReturn("月"); assertServiceException(() -> productsDetailService.create(reqVO), PRODUCTS_DETAIL_DURATION_EXIST, reqVO.getDuration(), ProductDurationUnitEnum.getDesc(reqVO.getDurationUnit())); } @@ -127,12 +153,14 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { when(productsMapper.selectOne(any())).thenReturn(mockProduct); + // mock exist ProductsDetailDO detail = new ProductsDetailDO(); + detail.setId(999L); detail.setProductId(mockProduct.getId()); detail.setDuration(12); detail.setDurationUnit(1); detail.setDeleted(false); - productsDetailMapper.insert(detail); + when(productsDetailMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(detail); // 构造请求 ProductDetailsSaveReqVO reqVO = new ProductDetailsSaveReqVO() @@ -144,13 +172,17 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { // 调用 productsDetailService.update(reqVO); - // 验证结果 - ProductsDetailDO updated = productsDetailMapper.selectById(detail.getId()); - assertEquals(6, updated.getDuration()); + // 校验状态更新 + verify(productsDetailMapper).update(argThat((LambdaUpdateWrapper wrapper) -> + wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSet().contains("discount") + && wrapper.getSqlSet().contains("duration") + && wrapper.getSqlSet().contains("duration_unit") + )); } @Test - void deleteTest(){ + void deleteTest() { // mock下架状态的产品 ProductsDO mockProduct = new ProductsDO(); mockProduct.setId(123L); @@ -160,11 +192,12 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { when(productsMapper.selectOne(any())).thenReturn(mockProduct); ProductsDetailDO detail = new ProductsDetailDO(); + detail.setId(999L); detail.setProductId(mockProduct.getId()); detail.setDuration(12); detail.setDurationUnit(1); detail.setDeleted(false); - productsDetailMapper.insert(detail); + when(productsDetailMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(detail); // 调用删除 productsDetailService.delete(detail.getId()); @@ -180,7 +213,7 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { detail.setId(321L); detail.setDeleted(false); detail.setProductId(123L); - productsDetailMapper.insert(detail); + when(productsDetailMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(detail); ProductsDetailDO result = productsDetailService.get(detail.getId()); assertNotNull(result); @@ -198,20 +231,6 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { o.setDeleted(false); }); - productsDetailMapper.insert(detail); - - // 不匹配 productId - productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setProductId(321L))); - - // 不匹配 duration - productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setDuration(2))); - - // 不匹配 discount - productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setDiscount(BigDecimal.valueOf(99)))); - - // 被逻辑删除 - productsDetailMapper.insert(cloneIgnoreId(detail, o -> o.setDeleted(true))); - // ============ 构造查询参数 ============ ProductDetailsPageReqVO reqVO = new ProductDetailsPageReqVO(); reqVO.setProductId(123L); @@ -219,6 +238,7 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setDiscount(BigDecimal.valueOf(100)); reqVO.setPageNo(1); reqVO.setPageSize(10); + when(productsDetailMapper.selectPage(reqVO)).thenReturn(new PageResult<>(List.of(detail), 1L)); // ============ 调用方法 ============ PageResult pageResult = productsDetailService.getPage(reqVO); @@ -284,7 +304,7 @@ public class ProductsDetailServiceImplTest extends BaseDbAndRedisUnitTest { detailDO.setDuration(1); detailDO.setDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); detailDO.setDiscount(BigDecimal.valueOf(85)); - productsDetailMapper.insert(detailDO); + when(productsDetailMapper.selectOne(any())).thenReturn(detailDO); BigDecimal discount = productsDetailService.getProductDetailOneYearDiscount(1L); assertEquals(BigDecimal.valueOf(85), discount); diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImplTest.java index 469395d02..9a4fb638c 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImplTest.java @@ -1,19 +1,25 @@ package com.cf.imes.module.system.service.funds.products; +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductPageReqVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductSaveReqVO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper; import com.cf.imes.module.system.enums.products.ProductStatusEnum; -import jakarta.annotation.Resource; +import org.apache.ibatis.builder.MapperBuilderAssistant; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.math.BigDecimal; +import java.util.List; -import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals; import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException; import static com.cf.imes.framework.test.core.util.RandomUtils.randomLongId; @@ -23,23 +29,26 @@ import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_IS_EXI import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_NO_DELETE; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_NO_EXIST; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_NO_UPDATE; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -/** - * @author Gqr - * @since 2025/10/14 9:46 - */ -@Import(ProductsServiceImpl.class) -public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { - @Resource + +class ProductsServiceImplTest extends BaseMockitoUnitTest { + @InjectMocks private ProductsServiceImpl productsService; - @Resource + @Mock private ProductsMapper productsMapper; + @BeforeAll + static void init(){ + TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), ProductsDO.class); + } + @Test void testCreateProductSuccess() { // 构造请求对象 @@ -50,14 +59,15 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { req.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); // 调用真实 Service 方法 - Long id = productsService.create(req); + productsService.create(req); - // 校验数据库插入结果 - ProductsDO result = productsMapper.selectById(id); - assertNotNull(result); - assertEquals(productName, result.getProductName()); - assertEquals(new BigDecimal("88.88"), result.getPrice()); - assertEquals(ProductStatusEnum.PRODUCT_UPDATES.getStatus(), result.getStatus()); + // 校验插入 + verify(productsMapper).insert(argThat((ProductsDO infoDO) -> + infoDO.getProductName().equals(req.getProductName()) + && infoDO.getPrice().equals(req.getPrice()) + && infoDO.getSoftwareId().equals(0) + && infoDO.getStatus().equals(req.getStatus()) + )); } /** @@ -65,15 +75,12 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { */ @Test void testUpdate_takeoff_to_listed() { - ProductSaveReqVO createVO = new ProductSaveReqVO(); - String productName = randomString(); - createVO.setProductName(productName); - createVO.setPrice(new BigDecimal("88.88")); - createVO.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); - Long id = productsService.create(createVO); + ProductsDO productsDO = new ProductsDO(); + productsDO.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); + when(productsMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(productsDO); ProductSaveReqVO updateVO = new ProductSaveReqVO(); - updateVO.setId(id); + updateVO.setId(100L); String newProductName = randomString(); updateVO.setProductName(newProductName); updateVO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); @@ -81,10 +88,13 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { productsService.update(updateVO); - ProductsDO db = productsMapper.selectById(id); - assertThat(db.getProductName()).isEqualTo(newProductName); - assertThat(db.getPrice()).isEqualByComparingTo("199.99"); - assertEquals(ProductStatusEnum.PRODUCT_UPDATES.getStatus(), db.getStatus()); + // 校验状态更新 + verify(productsMapper).update(argThat((LambdaUpdateWrapperX wrapper) -> + wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSet().contains("product_name") + && wrapper.getSqlSet().contains("price") + && wrapper.getSqlSet().contains("status") + )); } /** @@ -92,13 +102,12 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { */ @Test void testUpdate_statusUpdatableThrowsException() { - ProductSaveReqVO dbProduct = new ProductSaveReqVO(); - dbProduct.setProductName("产品"); - dbProduct.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); - Long id = productsService.create(dbProduct); + ProductsDO productsDO = new ProductsDO(); + productsDO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); + when(productsMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(productsDO); ProductSaveReqVO reqVO = new ProductSaveReqVO(); - reqVO.setId(id); + reqVO.setId(100L); reqVO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); // 非下架 assertServiceException(() -> productsService.update(reqVO), @@ -110,15 +119,12 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { */ @Test void testUpdate_listed_to_takeoff() { - ProductSaveReqVO createVO = new ProductSaveReqVO(); - String productName = randomString(); - createVO.setProductName(productName); - createVO.setPrice(new BigDecimal("88.88")); - createVO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); - Long id = productsService.create(createVO); + ProductsDO productsDO = new ProductsDO(); + productsDO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); + when(productsMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(productsDO); ProductSaveReqVO updateVO = new ProductSaveReqVO(); - updateVO.setId(id); + updateVO.setId(100L); String newProductName = randomString(); updateVO.setProductName(newProductName); updateVO.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); @@ -126,50 +132,52 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { productsService.update(updateVO); - ProductsDO db = productsMapper.selectById(id); - assertThat(db.getProductName()).isEqualTo(newProductName); - assertThat(db.getPrice()).isEqualByComparingTo("199.99"); - assertEquals(ProductStatusEnum.PRODUCT_DELIS.getStatus(), db.getStatus()); + // 校验状态更新 + verify(productsMapper).update(argThat((LambdaUpdateWrapperX wrapper) -> + wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSet().contains("product_name") + && wrapper.getSqlSet().contains("price") + && wrapper.getSqlSet().contains("status") + )); } @Test void testDelete() { - ProductSaveReqVO createVO = new ProductSaveReqVO(); - createVO.setProductName(randomString()); - createVO.setPrice(new BigDecimal("88.88")); - createVO.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); - Long id = productsService.create(createVO); + ProductsDO productsDO = new ProductsDO(); + productsDO.setId(100L); + productsDO.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); + when(productsMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(productsDO); - productsService.delete(id); + productsService.delete(productsDO.getId()); // 断言不存在了 - assertNull(productsMapper.selectById(id)); + assertNull(productsMapper.selectById(productsDO.getId())); } @Test void testDelete_listed() { - ProductSaveReqVO createVO = new ProductSaveReqVO(); - createVO.setProductName(randomString()); - createVO.setPrice(new BigDecimal("88.88")); - createVO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); - Long id = productsService.create(createVO); + ProductsDO productsDO = new ProductsDO(); + productsDO.setId(100L); + productsDO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); + when(productsMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(productsDO); - assertServiceException(() -> productsService.delete(id), + assertServiceException(() -> productsService.delete(productsDO.getId()), PRODUCTS_NO_DELETE); } @Test void testGet() { - ProductSaveReqVO createVO = new ProductSaveReqVO(); - String productName = randomString(); - createVO.setProductName(productName); - createVO.setPrice(new BigDecimal("88.88")); - createVO.setStatus(1); - Long id = productsService.create(createVO); - ProductsDO db = productsService.get(id); + ProductsDO productsDO = new ProductsDO(); + productsDO.setId(100L); + productsDO.setProductName("产品名称"); + productsDO.setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); + when(productsMapper.selectOne(any(LambdaQueryWrapperX.class))).thenReturn(productsDO); - assertThat(db).isNotNull(); - assertThat(db.getProductName()).isEqualTo(productName); + ProductsDO db = productsService.get(productsDO.getId()); + + assertEquals(db.getId(), productsDO.getId()); + assertEquals(db.getProductName(), productsDO.getProductName()); + assertEquals(db.getStatus(), productsDO.getStatus()); } @Test @@ -181,16 +189,6 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { o.setDeleted(false); o.setPrice(new BigDecimal("99.99")); }); - productsMapper.insert(dbProduct); - - // 不匹配 productName - productsMapper.insert(cloneIgnoreId(dbProduct, o -> o.setProductName("测试产品"))); - - // 不匹配 status - productsMapper.insert(cloneIgnoreId(dbProduct, o -> o.setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()))); - - // 被逻辑删除 - productsMapper.insert(cloneIgnoreId(dbProduct, o -> o.setDeleted(true))); // ============ 构造查询参数 ============ ProductPageReqVO reqVO = new ProductPageReqVO(); @@ -199,6 +197,8 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { reqVO.setPageNo(1); reqVO.setPageSize(10); + when(productsService.getPage(reqVO)).thenReturn(new PageResult<>(List.of(dbProduct), 1L)); + // ============ 调用方法 ============ PageResult pageResult = productsService.getPage(reqVO); @@ -211,19 +211,14 @@ public class ProductsServiceImplTest extends BaseDbAndRedisUnitTest { @Test void testDuplicateNameThrowsException() { + when(productsMapper.selectList(any(LambdaQueryWrapperX.class))).thenReturn(List.of(new ProductsDO())); + ProductSaveReqVO createVO = new ProductSaveReqVO(); String productName = randomString(); createVO.setProductName(productName); createVO.setPrice(new BigDecimal("88.88")); createVO.setStatus(1); - productsService.create(createVO); - - ProductSaveReqVO dup = new ProductSaveReqVO(); - dup.setProductName(productName); - dup.setStatus(1); - dup.setPrice(new BigDecimal("50.00")); - - assertServiceException(() -> productsService.create(dup), + assertServiceException(() -> productsService.create(createVO), PRODUCTS_IS_EXIST, productName); } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImplTest.java index 2722e3b69..8afa66e93 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImplTest.java @@ -1,10 +1,12 @@ package com.cf.imes.module.system.service.funds.purchase; import cn.hutool.core.collection.CollUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsRespVO; @@ -31,10 +33,12 @@ import com.cf.imes.module.system.service.funds.productpromotion.ProductPromotion import com.cf.imes.module.system.service.funds.products.ProductsDetailService; import com.cf.imes.module.system.service.organ.OrganService; import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils; -import jakarta.annotation.Resource; +import org.apache.ibatis.builder.MapperBuilderAssistant; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.math.BigDecimal; import java.time.LocalDate; @@ -45,6 +49,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException; import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_PRODUCT_PURCHASE_EXIST_ERROR; import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR; @@ -56,40 +61,48 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@Import(PurchaseServiceImpl.class) -class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { +class PurchaseServiceImplTest extends BaseMockitoUnitTest { - @Resource + @InjectMocks private PurchaseServiceImpl purchaseService; - @Resource + @Mock private PurchaseRecordMapper purchaseRecordMapper; - @MockitoBean + @Mock private OrganService organService; - @MockitoBean + @Mock private I18nUtils i18nUtils; - @MockitoBean + @Mock private ProductsDetailService productsDetailService; - @MockitoBean + @Mock private ProductDelayService productDelayService; - @MockitoBean + @Mock private ProductPromotionService productPromotionService; - @MockitoBean + @Mock private MybatisIdProperties mybatisIdProperties; + @BeforeAll + static void init(){ + TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), PurchaseRecordDO.class); + } + @Test void testCreateAndGetAndDeleteRecord() { // 准备参数 PurchaseRecordDO invoiceRecordsDO = randomPojo(PurchaseRecordDO.class, o -> { o.setId(1L); + o.setProductId(100L); o.setCreateTime(LocalDateTime.now()); o.setExternalSpent(new BigDecimal("100.00")); o.setProductName("测试产品"); @@ -99,8 +112,30 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); o.setOrganId(1L); }); + + // when purchaseService.createRecord(invoiceRecordsDO); + // then + ArgumentCaptor captor = + ArgumentCaptor.forClass(PurchaseRecordDO.class); + + verify(purchaseRecordMapper).insert(captor.capture()); + + PurchaseRecordDO actual = captor.getValue(); + assertEquals(1L, actual.getOrganId()); + assertEquals(100L, actual.getProductId()); + } + + @Test + void testGet(){ + PurchaseRecordDO invoiceRecordsDO = randomPojo(PurchaseRecordDO.class, o -> { + o.setId(1L); + o.setProductId(100L); + o.setTotalAmount(new BigDecimal("200.00")); + }); + when(purchaseRecordMapper.selectById(anyLong())).thenReturn(invoiceRecordsDO); + // 查询 PurchaseRecordDO result = purchaseService.getRecord(1L); @@ -108,31 +143,42 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { assertNotNull(result); assertEquals(invoiceRecordsDO.getProductName(), result.getProductName()); assertEquals(invoiceRecordsDO.getTotalAmount(), result.getTotalAmount()); + } - // 更新为可开票 - purchaseService.updateRecordInvoicable(1L, invoiceRecordsDO.getOrganId()); + @Test + void testUpdateReocrdInvoicable(){ + Long purchaseRecordId = 100L; + Long organId = 200L; - // 查询 - result = purchaseService.getRecord(1L); + // when + purchaseService.updateRecordInvoicable(purchaseRecordId, organId); - // 校验更新 - assertNotNull(result); - assertEquals(result.getIsInvocing(), INVOICABLE.getCode()); + // 校验状态更新 + verify(purchaseRecordMapper).update(argThat((LambdaUpdateWrapper wrapper) -> + wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSegment().contains("organ_id") + && wrapper.getSqlSet().contains("is_invocing") + )); + } - // 删除 - purchaseService.deleteRecord(1L); + @Test + void testDelete(){ + purchaseService.deleteRecord(100L); - // 查询 - result = purchaseService.getRecord(1L); - - // 验证删除 - assertNull(result); + // 校验状态更新 + verify(purchaseRecordMapper).update(argThat((LambdaUpdateWrapper wrapper) -> + wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSet().contains("deleted") + && wrapper.getSqlSet().contains("status") + )); } @Test void testGetPurchaseRecord_emptyResult() { PurchaseRecordPageReqVO pageReqVO = new PurchaseRecordPageReqVO(); + + when(purchaseRecordMapper.selectPage(pageReqVO)).thenReturn(new PageResult<>(null, 0L)); PageResult result = purchaseService.getPurchaseRecord(pageReqVO); @@ -154,11 +200,11 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); o.setOrganId(1L); }); - purchaseRecordMapper.insert(recordDO); PurchaseRecordPageReqVO pageReqVO = new PurchaseRecordPageReqVO(); pageReqVO.setEndTime(new LocalDate[]{LocalDate.now()}); // length != 2 + when(purchaseRecordMapper.selectPage(pageReqVO)).thenReturn(new PageResult(List.of(recordDO), 1l)); when(i18nUtils.getMessage(anyString())).thenReturn("支付宝"); when(organService.getOrganWithDeleted(anyLong())).thenReturn(null); @@ -184,14 +230,13 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); o.setOrganId(2L); }); - purchaseRecordMapper.insert(recordDO); PurchaseRecordPageReqVO pageReqVO = new PurchaseRecordPageReqVO(); pageReqVO.setEndTime(new LocalDate[]{ LocalDate.now().minusDays(1), LocalDate.now() }); - + when(purchaseRecordMapper.selectPage(pageReqVO)).thenReturn(new PageResult(List.of(recordDO), 1l)); when(i18nUtils.getMessage(anyString())).thenReturn("支付宝"); OrganizationDO organ = new OrganizationDO(); @@ -233,7 +278,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setOrganId(organId); o.setEndTime(LocalDate.now().plusDays(30)); }); - purchaseRecordMapper.insert(recordDO); + when(purchaseRecordMapper.selectOne(any())).thenReturn(recordDO); // mock:无延期记录 when(productDelayService.getRecordsByPurchaseId(recordDO.getId(), organId)) @@ -269,7 +314,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setOrganId(organId); o.setEndTime(originalEndTime); }); - purchaseRecordMapper.insert(recordDO); + when(purchaseRecordMapper.selectOne(any())).thenReturn(recordDO); // mock 延期记录(第一条为最新) ProductDelayRespVO delayVO = new ProductDelayRespVO(); @@ -290,22 +335,11 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { @Test void getInvoicingAmountTest(){ - // 准备参数 - PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { - o.setCreateTime(LocalDateTime.now()); - o.setExternalSpent(new BigDecimal("100.00")); - o.setProductName("测试产品"); - o.setTotalAmount(new BigDecimal("200.00")); - o.setStatus(PurchaseRecordStatusEnum.ACTIVE.getStatus()); - o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode()); - o.setIsInvocing(INVOICABLE.getCode()); - o.setInitial(false); - o.setOrganId(1L); - }); - purchaseRecordMapper.insert(recordDO); + BigDecimal amount = new BigDecimal(100); + when(purchaseRecordMapper.getInvoicingAmount(anyLong())).thenReturn(amount); BigDecimal invoicingAmount = purchaseService.getInvoicingAmount(1l); - assertEquals(recordDO.getTotalAmount(), invoicingAmount); + assertEquals(invoicingAmount, amount); } @Test @@ -337,34 +371,20 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { organId, Collections.singletonList(reqVO) ); - // 查询数据库验证 - List records = purchaseRecordMapper.selectList( - new LambdaQueryWrapper() - .eq(PurchaseRecordDO::getOrganId, organId) - .eq(PurchaseRecordDO::getProductId, productId) - ); - - assertEquals(1, records.size()); - - PurchaseRecordDO record = records.get(0); - - // 断言核心字段 - assertTrue(record.getId() > 0); - assertEquals("测试产品", record.getProductName()); - assertEquals(price, record.getTotalAmount()); - assertEquals(price, record.getOriginalAmount()); - - // monthAverageAmount = price / 10 - assertEquals(new BigDecimal("100.00"), record.getMonthAverageAmount()); - - // 初始化语义 - assertTrue(record.getInitial()); - assertEquals(1, record.getPurchaseDuration()); - assertEquals(ProductDurationUnitEnum.YEAR.getCode(), record.getPurchaseDurationUnit()); - assertEquals(PurchaseRecordStatusEnum.ACTIVE.getStatus(), record.getStatus()); - - // 过期时间 - assertEquals(LocalDate.now().minusDays(1), record.getEndTime()); + // 校验插入 + verify(purchaseRecordMapper).insert(argThat((PurchaseRecordDO purchaseRecordDO) -> + purchaseRecordDO.getProductName().equals(productsDO.getProductName()) + && purchaseRecordDO.getProductId().equals(productsDO.getId()) + && purchaseRecordDO.getPurchaseDuration().equals(1) + && purchaseRecordDO.getPurchaseDurationUnit().equals(ProductDurationUnitEnum.YEAR.getCode()) + && purchaseRecordDO.getProductDetailsId() == 0 + && purchaseRecordDO.getStatus().equals(PurchaseRecordStatusEnum.ACTIVE.getStatus()) + && purchaseRecordDO.getInitial().equals(true) + && purchaseRecordDO.getMonthAverageAmount().equals(new BigDecimal("100.00")) + && purchaseRecordDO.getTotalAmount().equals(price) + && purchaseRecordDO.getOriginalAmount().equals(price) + && purchaseRecordDO.getEndTime().equals(LocalDate.now().minusDays(1)) + )); } @Test @@ -384,7 +404,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { Long organId = 1L; // DB 中已有首购记录 - PurchaseRecordDO record = randomPojo(PurchaseRecordDO.class, o -> { + PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { o.setCreateTime(LocalDateTime.now()); o.setExternalSpent(new BigDecimal("100.00")); o.setProductName("测试产品"); @@ -395,20 +415,16 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); o.setOrganId(organId); }); - purchaseRecordMapper.insert(record); + purchaseRecordMapper.insert(recordDO); // 入参:updateList 中的 purchaseId 不存在 OrganCreateProductPurchaseReqVO reqVO = new OrganCreateProductPurchaseReqVO(); reqVO.setPurchaseId(9999L); reqVO.setPrice(new BigDecimal("1000")); - ServiceException ex = assertThrows(ServiceException.class, () -> - purchaseService.updateOrgInitProductPurchaseRecord( - organId, Collections.singletonList(reqVO) - ) - ); - - assertEquals(ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR.getCode(), ex.getCode()); + assertServiceException(() -> purchaseService.updateOrgInitProductPurchaseRecord( + organId, Collections.singletonList(reqVO) + ), ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR); } @Test @@ -417,7 +433,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { Long productId = 10L; // DB 中已有首购记录 - PurchaseRecordDO record = randomPojo(PurchaseRecordDO.class, o -> { + PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { o.setCreateTime(LocalDateTime.now()); o.setExternalSpent(new BigDecimal("100.00")); o.setProductName("测试产品"); @@ -429,20 +445,16 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setOrganId(organId); o.setProductId(productId); }); - purchaseRecordMapper.insert(record); + when(purchaseRecordMapper.selectList(any())).thenReturn(List.of(recordDO)); // 新增请求(purchaseId = null) OrganCreateProductPurchaseReqVO reqVO = new OrganCreateProductPurchaseReqVO(); reqVO.setProductId(productId); reqVO.setPrice(new BigDecimal("500")); - ServiceException ex = assertThrows(ServiceException.class, () -> - purchaseService.updateOrgInitProductPurchaseRecord( - organId, Collections.singletonList(reqVO) - ) - ); - - assertEquals(ORG_PRODUCT_PURCHASE_EXIST_ERROR.getCode(), ex.getCode()); + assertServiceException(() -> purchaseService.updateOrgInitProductPurchaseRecord( + organId, Collections.singletonList(reqVO) + ), ORG_PRODUCT_PURCHASE_EXIST_ERROR); } @Test @@ -472,8 +484,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setDeleted(false); }); - purchaseRecordMapper.insert(record1); - purchaseRecordMapper.insert(record2); + when(purchaseRecordMapper.selectList(any())).thenReturn(List.of(record1, record2)); // update 请求 OrganCreateProductPurchaseReqVO updateReq = new OrganCreateProductPurchaseReqVO(); @@ -502,20 +513,33 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { ); // 验证 update - PurchaseRecordDO updated = purchaseRecordMapper.selectById(3001L); - assertEquals(new BigDecimal("1000.00"), updated.getTotalAmount()); - assertEquals(new BigDecimal("100.00"), updated.getMonthAverageAmount()); + verify(purchaseRecordMapper).update(argThat((LambdaUpdateWrapper wrapper) -> + wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSegment().contains("organ_id") + && wrapper.getSqlSegment().contains("initial") + && wrapper.getSqlSet().contains("total_amount") + && wrapper.getSqlSet().contains("month_average_amount") + && wrapper.getSqlSet().contains("original_amount") + )); // 验证 delete(3002 被删) - assertNull(purchaseRecordMapper.selectById(3002L)); + verify(purchaseRecordMapper, times(1)).deleteByIds(List.of(record2.getId())); // 验证 create - List list = purchaseRecordMapper.selectList( - new LambdaQueryWrapper() - .eq(PurchaseRecordDO::getOrganId, organId) - .eq(PurchaseRecordDO::getProductId, 103L) - ); - assertEquals(1, list.size()); + // 校验插入 + verify(purchaseRecordMapper).insert(argThat((PurchaseRecordDO purchaseRecordDO) -> + purchaseRecordDO.getProductName().equals(productsDO.getProductName()) + && purchaseRecordDO.getProductId().equals(productsDO.getId()) + && purchaseRecordDO.getPurchaseDuration().equals(1) + && purchaseRecordDO.getPurchaseDurationUnit().equals(ProductDurationUnitEnum.YEAR.getCode()) + && purchaseRecordDO.getProductDetailsId() == 0 + && purchaseRecordDO.getStatus().equals(PurchaseRecordStatusEnum.ACTIVE.getStatus()) + && purchaseRecordDO.getInitial().equals(true) + && purchaseRecordDO.getMonthAverageAmount().equals(new BigDecimal("60.00")) + && purchaseRecordDO.getTotalAmount().equals(createReq.getPrice()) + && purchaseRecordDO.getOriginalAmount().equals(createReq.getPrice()) + && purchaseRecordDO.getEndTime().equals(LocalDate.now().minusDays(1)) + )); } @Test @@ -568,28 +592,10 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - public void testGetTotalSales() { + void testGetTotalSales() { // 准备数据 - PurchaseRecordDO r1 = randomPojo(PurchaseRecordDO.class, o -> { - o.setId(2001L); - o.setDeleted(false); - o.setTotalAmount(new BigDecimal("100.00")); - o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode()); - o.setIsInvocing(INVOICABLE.getCode()); - o.setInitial(false); - }); - - PurchaseRecordDO r2 = randomPojo(PurchaseRecordDO.class, o -> { - o.setId(2002L); - o.setDeleted(false); - o.setTotalAmount(new BigDecimal("300.00")); - o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - o.setInitial(false); - }); - - purchaseRecordMapper.insert(r1); - purchaseRecordMapper.insert(r2); + TotalSalesAmountRespVO totalSalesAmountRespVO = new TotalSalesAmountRespVO(new BigDecimal("400.00")); + when(purchaseRecordMapper.getTotalSales()).thenReturn(totalSalesAmountRespVO); TotalSalesAmountRespVO resp = purchaseService.getTotalSales(); @@ -598,7 +604,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - public void testGetManageSalesDetailsPage_success() { + void testGetManageSalesDetailsPage_success() { SalesDetailsPageReqVO reqVO = new SalesDetailsPageReqVO(); Long organId = 1L; @@ -613,7 +619,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); }); - purchaseRecordMapper.insert(recordDO); + when(purchaseRecordMapper.getSaleDetailsPage(reqVO)).thenReturn(new PageResult<>(List.of(recordDO), 1L)); // mock 国际化 when(i18nUtils.getMessage(anyString())).thenReturn("支付宝"); @@ -640,7 +646,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - public void testGetManageSalesDetailsPage_organNotExist() { + void testGetManageSalesDetailsPage_organNotExist() { SalesDetailsPageReqVO reqVO = new SalesDetailsPageReqVO(); reqVO.setPageNo(1); reqVO.setPageSize(10); @@ -657,7 +663,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setInitial(false); }); - purchaseRecordMapper.insert(recordDO); + when(purchaseRecordMapper.getSaleDetailsPage(reqVO)).thenReturn(new PageResult<>(List.of(recordDO), 1L)); when(i18nUtils.getMessage(anyString())).thenReturn("微信"); when(organService.getOrganWithDeleted(organId)).thenReturn(null); @@ -672,7 +678,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - public void testGetOrgInitialPurchaseRecord_success() { + void testGetOrgInitialPurchaseRecord_success() { Long organId = 1L; Long productId = 100L; @@ -686,7 +692,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); }); - purchaseRecordMapper.insert(initialRecord); + when(purchaseRecordMapper.selectOne(any())).thenReturn(initialRecord); PurchaseRecordDO result = purchaseService.getOrgInitialPurchaseRecord(organId, productId); @@ -697,7 +703,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { } @Test - public void testGetOrgProductPendingPurchaseList_success() { + void testGetOrgProductPendingPurchaseList_success() { Long organId = 3L; Long productId = 300L; @@ -711,18 +717,7 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); }); - // 干扰数据 - PurchaseRecordDO active = randomPojo(PurchaseRecordDO.class, o -> { - o.setOrganId(organId); - o.setProductId(productId); - o.setStatus(PurchaseRecordStatusEnum.ACTIVE.getStatus()); - o.setDeleted(false); - o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - }); - - purchaseRecordMapper.insert(pending1); - purchaseRecordMapper.insert(active); + when(purchaseRecordMapper.selectList(any())).thenReturn(List.of(pending1)); List result = purchaseService.getOrgProductPendingPurchaseList(organId, productId); @@ -734,14 +729,14 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { @Test void test_noInitialPurchase_withYearPricing_noPromotion() { - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; + Long productId = 100L; + Long organId = 1L; ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); + product.setId(productId); product.setPrice(new BigDecimal("1200")); - when(productsDetailService.validateProductExist(PRODUCT_ID)) + when(productsDetailService.validateProductExist(productId)) .thenReturn(product); ProductsDetailDO yearDetail = new ProductsDetailDO(); @@ -752,11 +747,11 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { when(productsDetailService.getPage(any())) .thenReturn(new PageResult<>(List.of(yearDetail), 1L)); - when(productPromotionService.getAvailableProductPromotionList(PRODUCT_ID)) + when(productPromotionService.getAvailableProductPromotionList(productId)) .thenReturn(Collections.emptyList()); List result = - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID); + purchaseService.getOrgProductDetailList(organId, productId); // 10个月 + 1年 assertEquals(11, result.size()); @@ -773,14 +768,14 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { @Test void test_withInitialPurchase_withYearPricing_withPromotion() { - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; + Long productId = 100L; + Long organId = 1L; ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); + product.setId(productId); product.setPrice(new BigDecimal("999")); - when(productsDetailService.validateProductExist(PRODUCT_ID)) + when(productsDetailService.validateProductExist(productId)) .thenReturn(product); ProductsDetailDO yearDetail = new ProductsDetailDO(); @@ -797,15 +792,15 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { promotion.setGiftDuration(3); promotion.setGiftDurationUnit(ProductDurationUnitEnum.MONTH.getCode()); - when(productPromotionService.getAvailableProductPromotionList(PRODUCT_ID)) + when(productPromotionService.getAvailableProductPromotionList(productId)) .thenReturn(List.of(promotion)); - PurchaseRecordDO record = new PurchaseRecordDO(); - record.setTotalAmount(new BigDecimal("1000")); - record.setMonthAverageAmount(new BigDecimal("100")); + PurchaseRecordDO recordDO = new PurchaseRecordDO(); + recordDO.setTotalAmount(new BigDecimal("1000")); + recordDO.setMonthAverageAmount(new BigDecimal("100")); ProductDetailsRespVO year = - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID) + purchaseService.getOrgProductDetailList(organId, productId) .stream() .filter(r -> r.getDurationUnit().equals(ProductDurationUnitEnum.YEAR.getCode())) .findFirst().orElseThrow(); @@ -821,14 +816,14 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { @Test void test_withInitialPurchase_withoutYearPricing_autoFillYear() { - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; + Long productId = 100L; + Long organId = 1L; ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); + product.setId(productId); product.setPrice(new BigDecimal("888")); - when(productsDetailService.validateProductExist(PRODUCT_ID)) + when(productsDetailService.validateProductExist(productId)) .thenReturn(product); // 只有 MONTH @@ -839,15 +834,15 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { when(productsDetailService.getPage(any())) .thenReturn(new PageResult<>(List.of(monthDetail), 1L)); - when(productPromotionService.getAvailableProductPromotionList(PRODUCT_ID)) + when(productPromotionService.getAvailableProductPromotionList(productId)) .thenReturn(Collections.emptyList()); - PurchaseRecordDO record = new PurchaseRecordDO(); - record.setTotalAmount(new BigDecimal("888")); - record.setMonthAverageAmount(new BigDecimal("88.8")); + PurchaseRecordDO recordDO = new PurchaseRecordDO(); + recordDO.setTotalAmount(new BigDecimal("888")); + recordDO.setMonthAverageAmount(new BigDecimal("88.8")); List result = - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID); + purchaseService.getOrgProductDetailList(organId, productId); ProductDetailsRespVO year = result.stream() @@ -860,20 +855,20 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { @Test void test_getInitialProductProductPriceNullError(){ - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; + Long productId = 100L; + Long organId = 1L; ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); + product.setId(productId); - when(productsDetailService.validateProductExist(PRODUCT_ID)) + when(productsDetailService.validateProductExist(productId)) .thenReturn(product); when(productsDetailService.getPage(any())) .thenReturn(new PageResult<>(anyList(), 1L)); ServiceException ex = assertThrows(ServiceException.class, () -> - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID) + purchaseService.getOrgProductDetailList(organId, productId) ); assertEquals(PRODUCT_PRICE_NULL_ERROR.getCode(), ex.getCode()); @@ -881,14 +876,14 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { @Test void test_getOrgProductDetailList_WithOrgInitial() { - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; + Long productId = 100L; + Long organId = 1L; ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); + product.setId(productId); product.setPrice(new BigDecimal("1000")); - when(productsDetailService.validateProductExist(PRODUCT_ID)) + when(productsDetailService.validateProductExist(productId)) .thenReturn(product); ProductsDetailDO yearDetail = new ProductsDetailDO(); @@ -902,13 +897,13 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { productPromotionDO.setPurchaseDuration(2); productPromotionDO.setPurchaseDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); // 优惠活动 - when(productPromotionService.getAvailableProductPromotionList(PRODUCT_ID)) + when(productPromotionService.getAvailableProductPromotionList(productId)) .thenReturn(Collections.singletonList(productPromotionDO)); // 插入首购记录 PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { - o.setOrganId(ORGAN_ID); - o.setProductId(PRODUCT_ID); + o.setOrganId(organId); + o.setProductId(productId); o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); o.setDeleted(false); o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); @@ -917,10 +912,10 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setMonthAverageAmount(new BigDecimal("99")); o.setTotalAmount(new BigDecimal("999")); }); - purchaseRecordMapper.insert(recordDO); + when(purchaseRecordMapper.selectOne(any())).thenReturn(recordDO); List result = - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID); + purchaseService.getOrgProductDetailList(organId, productId); ProductDetailsRespVO year = result.stream() @@ -928,71 +923,19 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { .findFirst().orElseThrow(); assertEquals(new BigDecimal("1198.80"), year.getCurrentPrice()); - assertEquals(new BigDecimal("1998.00"), year.getOriginalPrice()); - } - - @Test - void test_getOrgProductDetailList_WithYear() { - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; - - ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); - product.setPrice(new BigDecimal("1000")); - - when(productsDetailService.validateProductExist(PRODUCT_ID)) - .thenReturn(product); - - ProductsDetailDO yearDetail = new ProductsDetailDO(); - yearDetail.setDuration(2); - yearDetail.setDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); - yearDetail.setDiscount(new BigDecimal("60")); - when(productsDetailService.getPage(any())) - .thenReturn(new PageResult<>(List.of(yearDetail), 1L)); - - ProductPromotionDO productPromotionDO = new ProductPromotionDO(); - productPromotionDO.setPurchaseDuration(2); - productPromotionDO.setPurchaseDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); - // 优惠活动 - when(productPromotionService.getAvailableProductPromotionList(PRODUCT_ID)) - .thenReturn(Collections.singletonList(productPromotionDO)); - - // 插入首购记录 - PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { - o.setOrganId(ORGAN_ID); - o.setProductId(PRODUCT_ID); - o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); - o.setDeleted(false); - o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - o.setInitial(true); - o.setMonthAverageAmount(new BigDecimal("99")); - o.setTotalAmount(new BigDecimal("999")); - }); - purchaseRecordMapper.insert(recordDO); - - List result = - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID); - - ProductDetailsRespVO year = - result.stream() - .filter(r -> r.getDurationUnit().equals(ProductDurationUnitEnum.YEAR.getCode())) - .findFirst().orElseThrow(); - - assertEquals(new BigDecimal("1198.80"), year.getCurrentPrice()); - assertEquals(new BigDecimal("1998.00"), year.getOriginalPrice()); + assertEquals(new BigDecimal("1998"), year.getOriginalPrice()); } @Test void test_getOrgProductDetailList_WithoutYear() { - Long PRODUCT_ID = 100L; - Long ORGAN_ID = 1L; + Long productId = 100L; + Long organId = 1L; ProductsDO product = new ProductsDO(); - product.setId(PRODUCT_ID); + product.setId(productId); product.setPrice(new BigDecimal("1000")); - when(productsDetailService.validateProductExist(PRODUCT_ID)) + when(productsDetailService.validateProductExist(productId)) .thenReturn(product); ProductsDetailDO monthDetail = new ProductsDetailDO(); @@ -1005,13 +948,13 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { productPromotionDO.setPurchaseDuration(2); productPromotionDO.setPurchaseDurationUnit(ProductDurationUnitEnum.YEAR.getCode()); // 优惠活动 - when(productPromotionService.getAvailableProductPromotionList(PRODUCT_ID)) + when(productPromotionService.getAvailableProductPromotionList(productId)) .thenReturn(Collections.singletonList(productPromotionDO)); // 插入首购记录 PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { - o.setOrganId(ORGAN_ID); - o.setProductId(PRODUCT_ID); + o.setOrganId(organId); + o.setProductId(productId); o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); o.setDeleted(false); o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); @@ -1020,10 +963,10 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { o.setMonthAverageAmount(new BigDecimal("99")); o.setTotalAmount(new BigDecimal("999")); }); - purchaseRecordMapper.insert(recordDO); + when(purchaseRecordMapper.selectOne(any())).thenReturn(recordDO); List result = - purchaseService.getOrgProductDetailList(ORGAN_ID, PRODUCT_ID); + purchaseService.getOrgProductDetailList(organId, productId); ProductDetailsRespVO year = result.stream() @@ -1040,26 +983,16 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { Long organId = 1L; Long recordId = 101L; - PurchaseRecordDO recordDO = randomPojo(PurchaseRecordDO.class, o -> { - o.setId(recordId); - o.setOrganId(organId); - o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); - o.setDeleted(false); - o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - o.setInitial(true); - o.setMonthAverageAmount(new BigDecimal("99")); - o.setTotalAmount(new BigDecimal("999")); - }); - - purchaseRecordMapper.insert(recordDO); - purchaseService.invalidHistoryOrganProductPurchaseRecord(organId, recordId); - PurchaseRecordDO updated = - purchaseRecordMapper.selectById(recordId); - - assertEquals(PurchaseRecordStatusEnum.INACTIVE.getStatus(), updated.getStatus()); + // 校验状态更新 + verify(purchaseRecordMapper).update(argThat((LambdaUpdateWrapper wrapper) -> + wrapper.getSqlSegment().contains("organ_id") + && wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSegment().contains("deleted") + && wrapper.getSqlSegment().contains("status") + && wrapper.getSqlSet().contains("status") + )); } @Test @@ -1067,60 +1000,25 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { Long organId = 1L; Long recordId = 200L; - PurchaseRecordDO record = randomPojo(PurchaseRecordDO.class, o -> { - o.setId(recordId); - o.setOrganId(organId); - o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); - o.setDeleted(false); - o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - o.setInitial(true); - o.setMonthAverageAmount(new BigDecimal("99")); - o.setTotalAmount(new BigDecimal("999")); - }); - - purchaseRecordMapper.insert(record); - // when purchaseService.activateHistoryOrganProductPurchaseRecord(organId, recordId); - // then - PurchaseRecordDO updated = purchaseRecordMapper.selectById(recordId); - - assertEquals( - PurchaseRecordStatusEnum.ACTIVE.getStatus(), - updated.getStatus() - ); + // 校验状态更新 + verify(purchaseRecordMapper).update(argThat((LambdaUpdateWrapper wrapper) -> + wrapper.getSqlSegment().contains("organ_id") + && wrapper.getSqlSegment().contains("id") + && wrapper.getSqlSegment().contains("deleted") + && wrapper.getSqlSegment().contains("status") + && wrapper.getSqlSet().contains("status") + )); } @Test void should_return_correct_sales_statistics() { - Long organId = 1L; - PurchaseRecordDO record1 = randomPojo(PurchaseRecordDO.class, o -> { - o.setOrganId(organId); - o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); - o.setDeleted(false); - o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - o.setInitial(false); - o.setMonthAverageAmount(new BigDecimal("99")); - o.setTotalAmount(new BigDecimal("200")); - o.setCreateTime(LocalDateTime.now().minusDays(2)); - }); - - PurchaseRecordDO record2 = randomPojo(PurchaseRecordDO.class, o -> { - o.setOrganId(organId); - o.setStatus(PurchaseRecordStatusEnum.PENDING.getStatus()); - o.setDeleted(false); - o.setPaymentMethod(PayChannelCodeEnum.WECHAT_NATIVE.getCode()); - o.setIsInvocing(INVOICINGSUCCESSFUL.getCode()); - o.setInitial(false); - o.setTotalAmount(new BigDecimal("100")); - o.setCreateTime(LocalDateTime.now()); - }); - purchaseRecordMapper.insert(record1); - purchaseRecordMapper.insert(record2); + TotalSalesAmountRespVO totalSalesAmountRespVO = new TotalSalesAmountRespVO(new BigDecimal(300)); + when(purchaseRecordMapper.getTotalSales()).thenReturn(totalSalesAmountRespVO); + when(purchaseRecordMapper.getTodaySales(any())).thenReturn(new BigDecimal(100)); // when ManageSalesTotalStatisticRespVO resp = @@ -1128,8 +1026,8 @@ class PurchaseServiceImplTest extends BaseDbAndRedisUnitTest { // then assertAll( - () -> assertEquals(new BigDecimal("300.00"), resp.getSalesTotal()), - () -> assertEquals(new BigDecimal("100.00"), resp.getSalesToday()) + () -> assertEquals(new BigDecimal("300"), resp.getSalesTotal()), + () -> assertEquals(new BigDecimal("100"), resp.getSalesToday()) ); } } \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/statistics/FundsStatisticsServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/statistics/FundsStatisticsServiceImplTest.java index e5a52f753..643186718 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/statistics/FundsStatisticsServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/funds/statistics/FundsStatisticsServiceImplTest.java @@ -1,28 +1,23 @@ package com.cf.imes.module.system.service.funds.statistics; import com.cf.imes.framework.common.enums.StatisticsUnit; -import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils; -import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; -import com.cf.imes.framework.security.test.WithMockLoginUser; -import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest; -import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganFundsStatisticsReqVO; +import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.controller.admin.statistics.vo.OrgStatusGroupStatisticsReqVO; -import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO; +import com.cf.imes.module.system.dal.dataobject.funds.statistics.FundsTradeTypeGroupStatisticsDO; import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper; -import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.mockito.InjectMocks; +import org.mockito.Mock; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; /** * @@ -30,23 +25,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; * @author Gqr * @since 2025/12/31 15:20 */ -@Import(FundsStatisticsServiceImpl.class) -public class FundsStatisticsServiceImplTest extends BaseDbAndRedisUnitTest { +class FundsStatisticsServiceImplTest extends BaseMockitoUnitTest { - @Resource + @InjectMocks private FundsStatisticsServiceImpl fundsStatisticsService; - @MockitoBean - private I18nUtils i18nUtils; - - @Resource + @Mock private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper; @Test - @WithMockLoginUser(organId = 1L) void should_return_consumption_trend_with_zero_filling() { - Long organId = SecurityFrameworkUtils.getUserOrganId(); - OrgStatusGroupStatisticsReqVO reqVO = new OrgStatusGroupStatisticsReqVO(); reqVO.setUnit(StatisticsUnit.DAY.getValue()); reqVO.setCreateTime(new LocalDate[]{ @@ -54,24 +42,10 @@ public class FundsStatisticsServiceImplTest extends BaseDbAndRedisUnitTest { LocalDate.now().plusDays(1) }); - IncomeExpenseDetailsDO pojo1 = randomPojo(IncomeExpenseDetailsDO.class, o -> { - o.setOrganId(organId); - o.setAmount(new BigDecimal("100")); - o.setCreateTime(LocalDateTime.now().minusDays(2)); - }); - IncomeExpenseDetailsDO pojo2 = randomPojo(IncomeExpenseDetailsDO.class, o -> { - o.setOrganId(organId); - o.setAmount(new BigDecimal("200")); - o.setCreateTime(LocalDateTime.now()); - }); - IncomeExpenseDetailsDO pojo3 = randomPojo(IncomeExpenseDetailsDO.class, o -> { - o.setAmount(new BigDecimal("200")); - o.setCreateTime(LocalDateTime.now()); - }); - - incomeExpenseDetailsMapper.insert(pojo1); - incomeExpenseDetailsMapper.insert(pojo2); - incomeExpenseDetailsMapper.insert(pojo3); + List purchaseList = new ArrayList<>(); + purchaseList.add(new FundsTradeTypeGroupStatisticsDO(new BigDecimal("100"), "2026-1-18")); + purchaseList.add(new FundsTradeTypeGroupStatisticsDO(new BigDecimal("400"), "2026-1-20")); + when(incomeExpenseDetailsMapper.selectTotalSalesTrendGroupByCreateTime(reqVO)).thenReturn(purchaseList); // when query Map result = @@ -88,9 +62,9 @@ public class FundsStatisticsServiceImplTest extends BaseDbAndRedisUnitTest { assertArrayEquals( new BigDecimal[]{ - new BigDecimal("100.00"), + new BigDecimal("100"), BigDecimal.ZERO, - new BigDecimal("400.00"), + new BigDecimal("400"), BigDecimal.ZERO, }, data