Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mockito @Mock does not inject into named @Resource as expected

I have a class with three named @Resource members as follows:

@Resource(name = "contactsPaginationRequestValidator")
private PaginationRequestValidator paginationRequestValidator;

@Resource(name = "integerMaxPaginationRequestValidator")
private PaginationRequestValidator integerMaxPaginationRequestValidator;

@Resource(name = "contactsSearchResultPaginationRequestValidator")
private PaginationRequestValidator contactsSearchResultPaginationRequestValidator;

After upgrading to Mockito 1.9.5 from 1.8.5, the test began failing. The test suite mocked PaginationRequestValidator only once as follows:

@Mock
private PaginationRequestValidator mockPaginationRequestValidator;

This resulted in only the third of the three instances being injected as the following sysout makes clear:

paginationRequestValidator (contactsPaginationRequestValidator) is null
integerMaxPaginationRequestValidator (integerMaxPaginationRequestValidator) is null
contactsSearchResultPaginationRequestValidator (contactsSearchResultPaginationRequestValidator) is mockPaginationRequestValidator

Obviously, there was a change in behavior between the two versions. I am assuming the older version injected the mock into all three of fields - which would still be an acceptable solution to me.

Being the smart guy that I am, I figured I could get the test to pass by providing the name associated with the resource, as follows:

@Mock(name = "contactsPaginationRequestValidator")
private PaginationRequestValidator mockPaginationRequestValidator;

This resulted in similar, but subtly different results. The third field, not the expected targeted field was mocked, as above, but the it was mocked with the name provided in the @Mock. See the sysout:

paginationRequestValidator (contactsPaginationRequestValidator) is null
integerMaxPaginationRequestValidator (integerMaxPaginationRequestValidator) is null
contactsSearchResultPaginationRequestValidator (contactsSearchResultPaginationRequestValidator) is contactsPaginationRequestValidator

This is totally unexpected behavior. Yet, there is more. When I then added a similar mock for the second field, all the fields ended being mocked as expected:

@Mock(name = "contactsPaginationRequestValidator")
private PaginationRequestValidator mockPaginationRequestValidator;

@Mock(name = "integerMaxPaginationRequestValidator")
private PaginationRequestValidator mockIntegerMaxPaginationRequestValidator;

Sysout:

paginationRequestValidator (contactsPaginationRequestValidator) is contactsPaginationRequestValidator
integerMaxPaginationRequestValidator (integerMaxPaginationRequestValidator) is integerMaxPaginationRequestValidator
contactsSearchResultPaginationRequestValidator (contactsSearchResultPaginationRequestValidator) is null

While this is exactly as I would expect, it seems completely contradictory to the previous tries.

I have the documentation that explains this behavior, but it does not suggest a way to inject the same mock into all three. Is this possible, or must I create multiple mocks and then change individual test cases to use the "correct" mock?

The test suite uses the @InjectMocks annotation.

like image 387
Bill Turner Avatar asked Mar 19 '14 20:03

Bill Turner


1 Answers

The documentation of InjectMocks says:

Field injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the field name and the mock name.

So you need 3 mocks, each having the name of the field to inject with the mock.

like image 135
JB Nizet Avatar answered Oct 03 '22 12:10

JB Nizet