如何使用Mockito正确模拟对象

时间:2017-07-19 12:09:35

标签: java junit mockito

我正在尝试测试下面的ClientDetails类,并尝试同时学习JUnit和Mockito。

// this is the class I'm trying to test
public class ClientDetails {

    @Autowired private IApplicantService<Applicant> applicantService;
    @Autowired private ClientDetailsHelpers helpers;

    public FullClientDetails getClientDetails(String businessId, boolean isNewClient) {

        FullClientDetails fcd = new FullClientDetails(); 

        ClientParams params = new ClientParams();
        params.setBusinessId(businessId);

        ApplicantId ai = applicantService.retrieveApplicantIdFromBusinessId(params);
        Long applicantId = ai.getApplicantId();
        params.setApplicantId(applicantId);

        Applicant applicant = applicantService.retrieveApplicantDetailsByHerdNumber(params);
        helpers.validateRetrievedApplicant(applicant, isNewClient, businessId);

        fcd.setApplicant(applicant);
        // more method calls that get and assign objects to the fcd object

        return fcd;
    }


}
// ClientDetailsHelpers.java method that throws exception
public void validateRetrievedApplicant(Applicant applicant, boolean isNewClient, String businessId) {
    if (applicant.getApplicantId() == null && !isNewClient) {
        throw new ValidationSearchException(businessId);
    }
}
// test class
@RunWith(MockitoJUnitRunner.class)
public class ClientDetailsTest {

    private final static String BUSINESS_ID = "A1234567";
    private final static Long APPLICANT_ID = null;

    @InjectMocks
    ClientDetails clientDetails;

    @Mock ApplicantServiceImpl applicantService;
    @Mock ClientDetailsHelpers helpers;

    private ApplicantParams params;
    private Applicant applicantWithInvalidId = new Applicant();

    ApplicantId applicantId = new ApplicantId(APPLICANT_ID, BUSINESS_ID);

    @Before
    public void before(){
        applicantWithInvalidId.setApplicantId(null);
    }

    @Test(expected = ValidationSearchException.class)
    public void testGetFullApplicationDetails(){
        when(applicantService.retrieveApplicantIdFromBusinessId(Mockito.any(ApplicantParams.class))).thenReturn(applicantId);
        when(applicantService.retrieveApplicantDetailsByHerdNumber(Mockito.any(ApplicantParams.class))).thenReturn(applicantWithInvalidId);
        FullClientDetails fcd = clientDetails.getFullClientDetails(BUSINESS_ID , false);
    }
}

在我的测试类中,我创建了一些模拟对象,包括 applicantService 时要返回的 ApplicantId 对象。 retrieveApplicantIdFromBusinessId()被调用并且当 applicantService retrieveApplicantDetailsByHerdNumber()被调用时,申请人对象的applicantId属性设置为null。

ClientDetailsHelper validateRetrievedApplicant()函数应该在申请人时抛出异常。 getApplicantId()返回null,如果布尔 isNewClient 设置为false,但它似乎没有在测试中发生,它不会抛出任何异常并且@Test失败。

我最好的猜测是我没有使用 when()。thenReturn()来正确返回我创建的Applicant和ApplicantId对象,而是另一个Applicant对象传递给validateRetrievedApplicant()和当它到达验证方法时返回和applicantId为0。

有什么建议吗?谢谢!

1 个答案:

答案 0 :(得分:1)

您的代码没有抛出异常,因为您正在测试的代码中没有任何地方抛出该异常。我假设您的异常是在ClientDetailsHelpers类中抛出的,但是您正在模拟此类,因此它不会调用实际代码,因此不会抛出任何异常。

您需要考虑要测试的内容。您是否希望将ClientDetails类作为一个单元进行隔离测试?在这种情况下,您不必担心抛出异常,因为它不属于该类的功能。

第二个选项是你想要进行更多的集成测试,你可以在其中引入一个实际的ClientDetailsHelpers类,但为了做到这一点,你需要在测试中包含一些配置,以确保这个bean可用于测试Spring上下文。您可以使用Spring4JunitRunner而不是Mockito来执行此操作,然后使用测试类中的@ContextConfiguration(MyConfig.class)注释为ClientDetailsHelpers类提供组件扫描的配置类,其中MyConfig是相关的Spring配置类。