Java单元测试中如何测试Update方法 现有测试代码是否合理
针对你的问题逐一解答:
1. 你标注的那行when(companyRepository.save(any())).thenReturn(company);是否必要?
在你当前的测试逻辑下属于冗余内容,可以删除。因为你当前的测试只校验了传入save方法的实体属性是否正确,没有校验接口返回的CompanyDTO内容,所以就算不打这个桩,测试也能正常运行。
但如果你后续要补全DTO返回值的校验逻辑,这行桩就需要保留——你甚至可以返回一个全新构造的、已更新的Company实例,来验证你的业务代码确实是用save方法返回的结果来构造DTO,而不是直接用了修改后的原实体。
2. 你当前的测试还存在哪些遗漏?
- 缺少返回值校验:仅校验了入参正确,没有确认最终返回的
CompanyDTO属性和预期更新后的属性一致。 - 缺少异常场景覆盖:没有测试
uuid不存在、findByUuid返回空的场景,此时业务代码应该抛出EntityNotFoundException,且save方法不会被调用。 - 缺少非更新字段校验:如果你的
Company实体还有其他字段(比如uuid、创建时间等),需要确认这些字段不会被update方法意外修改。
3. 关于@Spy和@Captor的选择
你用@Captor是完全正确的,这里不需要用@Spy。@Spy用于对真实对象的行为进行监听和部分桩化,你这里只需要捕获save方法的入参,验证实体的更新逻辑是否正确,用@Captor是最优选择。
优化后的测试示例:
@InjectMocks private CompanyServiceImpl companyService; @Mock private CompanyRepository companyRepository; @Captor ArgumentCaptor<Company> companyCaptorEntity; @Test public void testUpdate_正常更新成功() { // 1. 构造测试数据 final UUID uuid = UUID.randomUUID(); final String updatedName = "更新后的公司名称"; final CompanyRequest request = new CompanyRequest(); request.setName(updatedName); final Company originalCompany = new Company(); originalCompany.setUuid(uuid); originalCompany.setName("原始公司名称"); // 2. 打依赖桩 when(companyRepository.findByUuid(uuid)).thenReturn(Optional.of(originalCompany)); // 这里返回一个新构造的实例,验证业务代码确实用了save的返回值构造DTO final Company savedCompany = new Company(); savedCompany.setUuid(uuid); savedCompany.setName(updatedName); when(companyRepository.save(any(Company.class))).thenReturn(savedCompany); // 3. 执行测试方法 CompanyDTO result = companyService.update(request, uuid); // 4. 校验调用逻辑 Mockito.verify(companyRepository).findByUuid(uuid); Mockito.verify(companyRepository).save(companyCaptorEntity.capture()); // 5. 校验传入save的实体属性正确 Company capturedCompany = companyCaptorEntity.getValue(); assertEquals(updatedName, capturedCompany.getName()); assertEquals(uuid, capturedCompany.getUuid()); // 确认非更新字段未被修改 // 6. 校验返回DTO符合预期 assertEquals(updatedName, result.getName()); assertEquals(uuid, result.getUuid()); } @Test public void testUpdate_uuid不存在_抛出异常() { // 1. 构造测试数据 final UUID notExistsUuid = UUID.randomUUID(); final CompanyRequest request = new CompanyRequest(); request.setName("测试名称"); // 2. 打依赖桩,返回空 when(companyRepository.findByUuid(notExistsUuid)).thenReturn(Optional.empty()); // 3. 执行并校验抛出指定异常 assertThrows(EntityNotFoundException.class, () -> companyService.update(request, notExistsUuid)); // 4. 校验save方法未被调用 Mockito.verify(companyRepository, never()).save(any()); }
内容的提问来源于stack exchange,提问作者user17186249
相关产品推荐
相关产品推荐

