You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JUnit测试Rest API的Update方法?测试触发EntityNotFoundException

问题分析与解决方案

你的测试代码存在几个关键问题,导致抛出EntityNotFoundException:

  1. 错误Mock了被测试类的方法:你在测试中Mock了applicantService.update(),这相当于跳过了真实的更新逻辑,完全失去了单元测试的意义——单元测试要验证的就是这个方法的真实行为,不能Mock它自己。
  2. 未Mock依赖的Repository查询逻辑:update()方法调用了getById(id),而getById底层依赖applicantRepository.findById(),你没有Mock这个方法的返回值,导致它返回空Optional,触发了实体找不到的异常。
  3. 测试逻辑完全偏离:你没有实际调用applicantService.update()方法,只是断言了两个预设对象的属性,根本没测试到update的业务逻辑。
  4. 参数传递错误:测试中使用Mockito.any()作为update的id参数,但实际调用时没有传入有效的id值,导致id为null,这也是报错里显示id : null的直接原因。

修正后的测试代码

@ExtendWith(MockitoExtension.class)
class ApplicantServiceTest {

    @Mock
    private ApplicantRepository applicantRepository;
    @Mock
    private CreditRatingService creditRatingService;
    @Mock
    private ApplicantMapper applicantMapper;

    @InjectMocks
    private ApplicantService applicantService;

    @Test
    void update() {
        // 1. 准备测试数据:原有的申请人数据(确保id不为空)
        Long applicantId = 1L;
        Applicant originalApplicant = getSampleApplicants().get(1);
        originalApplicant.setId(applicantId);

        // 2. 构造要更新的DTO(模拟前端传入的更新请求)
        ApplicantDTO updateDTO = new ApplicantDTO();
        updateDTO.setFirstName("ege");
        updateDTO.setLastName("c0skun");
        updateDTO.setMonthlyIncome(2523);
        updateDTO.setPhoneNumber("21412412");
        updateDTO.setIdentificationNumber(2141245L);

        // 3. Mock Repository的findById方法,确保getById能拿到数据
        Mockito.when(applicantRepository.findById(applicantId))
               .thenReturn(Optional.of(originalApplicant));

        // 4. 构造预期的更新后数据(与DTO中的更新字段对应)
        Applicant expectedUpdatedApplicant = new Applicant();
        BeanUtils.copyProperties(originalApplicant, expectedUpdatedApplicant);
        expectedUpdatedApplicant.setFirstName(updateDTO.getFirstName());
        expectedUpdatedApplicant.setLastName(updateDTO.getLastName());
        expectedUpdatedApplicant.setMonthlyIncome(updateDTO.getMonthlyIncome());
        expectedUpdatedApplicant.setPhoneNumber(updateDTO.getPhoneNumber());
        expectedUpdatedApplicant.setIdentificationNumber(updateDTO.getIdentificationNumber());

        // 5. Mock Repository的save方法返回预期结果
        Mockito.when(applicantRepository.save(Mockito.any(Applicant.class)))
               .thenReturn(expectedUpdatedApplicant);

        // 6. 实际调用要测试的update方法
        Applicant actualUpdatedApplicant = applicantService.update(updateDTO, applicantId);

        // 7. 断言更新后的属性是否符合预期
        Assert.assertEquals(expectedUpdatedApplicant.getIdentificationNumber(), actualUpdatedApplicant.getIdentificationNumber());
        Assert.assertEquals(expectedUpdatedApplicant.getPhoneNumber(), actualUpdatedApplicant.getPhoneNumber());
        Assert.assertEquals(expectedUpdatedApplicant.getFirstName(), actualUpdatedApplicant.getFirstName());
        Assert.assertEquals(expectedUpdatedApplicant.getMonthlyIncome(), actualUpdatedApplicant.getMonthlyIncome());
        Assert.assertEquals(expectedUpdatedApplicant.getId(), actualUpdatedApplicant.getId());

        // 8. 验证Repository方法是否被正确调用
        Mockito.verify(applicantRepository, Mockito.times(1)).findById(applicantId);
        Mockito.verify(applicantRepository, Mockito.times(1)).save(Mockito.any(Applicant.class));
    }
}

关键修正点说明

  • Mock Repository核心方法:通过Mockito.when(applicantRepository.findById(applicantId))预设查询结果,确保getById(id)能拿到有效数据,避免抛出异常。
  • 调用真实业务方法:直接调用applicantService.update(),传入构造好的DTO和有效id,触发真实的更新逻辑。
  • 验证依赖调用:使用Mockito.verify()确认Repository的查询和保存操作确实被执行,保证业务逻辑的完整性。
  • 明确数据流向:从原始数据→更新DTO→预期结果→实际结果,完整覆盖update方法的业务流程。

内容的提问来源于stack exchange,提问作者Ege Coskun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 00:15:59