mockito 如何测试Rest API中的更新功能?

8zzbczxx  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(188)

我无法使用JUnit测试我的update方法。我正在模拟必要的存储库和服务。但是当我调用findById(Mockito.any())时,它找不到任何东西,所以抛出了一个异常。
下面是我的测试类:

@ExtendWith(MockitoExtension.class)
class ApplicantServiceTest {

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

    @InjectMocks
    private ApplicantService applicantService;

    @Test
    void update() {
        Applicant applicant = getSampleApplicants().get(1);
        Applicant updatedApplicant = new Applicant(1L,2141245L,"ege","c0skun",2523,"21412412",null,null);

        Mockito.when(applicantService.update(applicantMapper.toDTO(applicant),Mockito.any())).thenReturn(applicant);

        Assert.assertEquals(applicant.getIdentificationNumber(),updatedApplicant.getIdentificationNumber());
        Assert.assertEquals(applicant.getPhoneNumber(), updatedApplicant.getPhoneNumber());
        Assert.assertEquals(applicant.getFirstName(), updatedApplicant.getFirstName());
        assertEquals(applicant.getMonthlyIncome(), updatedApplicant.getMonthlyIncome());
        Assert.assertEquals(applicant.getId(), updatedApplicant.getId());

    }

而这正是我试图测试的方法:

public Applicant update(ApplicantDTO applicantDTO,Long id) {

        Applicant byId = getById(id);

        if (applicantDTO.getMonthlyIncome()!=byId.getMonthlyIncome()){
            byId.setMonthlyIncome(applicantDTO.getMonthlyIncome());
        }
        if (!Objects.equals(applicantDTO.getFirstName(), byId.getFirstName())){
            byId.setFirstName(applicantDTO.getFirstName());
        }
        if (!Objects.equals(applicantDTO.getLastName(), byId.getLastName())){
            byId.setLastName(applicantDTO.getLastName());
        }
        if (!Objects.equals(applicantDTO.getPhoneNumber(), byId.getPhoneNumber())){
            byId.setPhoneNumber(applicantDTO.getPhoneNumber());
        }
        if (!Objects.equals(applicantDTO.getIdentificationNumber(), byId.getIdentificationNumber())){
            byId.setIdentificationNumber(applicantDTO.getIdentificationNumber());
        }

        return applicantRepository.save(byId);
    }

以下是输出:

17:43:19.520 [main] ERROR com.egecoskun.finalproject.services.ApplicantService - Applicant not found by id : null

Related Applicant not found with : [id : null]
EntityNotFoundException(details=Some Special Details)
    at com.egecoskun.finalproject.services.ApplicantService.lambda$getById$0(ApplicantService.java:47)
    at java.base/java.util.Optional.orElseThrow(Optional.java:403)
    at com.egecoskun.finalproject.services.ApplicantService.getById(ApplicantService.java:45)
    at com.egecoskun.finalproject.services.ApplicantService.update(ApplicantService.java:75)
    at com.egecoskun.finalproject.services.ApplicantServiceTest.update(ApplicantServiceTest.java:136)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...

有人能解释一下如何对我的更新方法进行单元测试吗?

fgw7neuy

fgw7neuy1#

测试代码的问题在于,您混淆了模拟对象的方法(例如applicantRepository)和调用被测对象的测试方法(applicantService)。我们使用when(...)定义Mockito中的模拟行为,然后应该调用实际测试的代码(没有when())。
您可能要做的是:mock通过ID检索applicant对象,mock保存修改后的对象,运行update方法对其进行测试并Assert结果。
要模拟applicantRepository的行为,您需要告诉Mockito它的方法调用的预期结果是什么,例如(我对未附加的代码做了一些假设):

when(applicantRepository.findById(anyLong())).thenReturn(applicantFromDb);
when(applicantRepository.save(notNull())).thenAnswer(returnsFirstArg());

applicantFromDb是在测试方法中创建的对象)
之后,当您调用update方法时,将使用上面的模拟行为:

Applicant result = applicantService.update(...);

现在,您可以Assert从测试方法返回的结果。

fnvucqvd

fnvucqvd2#

ApplicationService是你的测试类。你得到的异常来自于你测试的update()方法开始时调用的ApplicationService.getById()方法。你没有向我们展示那个方法,但是猜测它调用仓库来通过id获得一个示例。你的仓库模拟没有设置为在被要求任何实体时返回任何东西,因此它返回null,这似乎触发了getById()方法中的orElseThrow子句。
因此,您看到的可能是预期的行为-当尝试使用存储库中不存在的id进行更新时(存储库返回空值),服务抛出异常。如果您想测试实体存在的情况,您需要适当地模拟存储库。

相关问题