Mockito - Mocking/verifying an object parameter without equals() method
Mockito is a powerful mock/stub library for unit tests in Java. This blogpost is written assuming the reader is comfortable with using Mockito.
While using Mockito in my unit tests, I have come across a problem regarding
classes from third party libraries. This class has no equals()
method
implemented and I had to keep it in a method’s parameters. Let’s assume it’s
something like follows:
public interface UserService {
User search(int limit, SearchQuery searchQuery);
}
A sample test code would be as follows:
@Test
public void mockTest() {
UserService mockService = Mockito.mock(UserService.class);
Mockito.when(mockService.search(10, new SearchQuery())).thenReturn(testUser);
User actual = new UserSearcher(mockService).search(10, new SearchQuery());
assertEquals(testUser, actual); //fails
Mockito.verify(mockService).search(10, new SearchQuery()); //also fails
}
Please assume testUser
is initialized properly and UserSearcher
class is a
simple delegator as below:
public class UserSearcher {
private UserService service;
public UserSearcher(UserService service) {
this.service = service;
}
public User search(int limit, SearchQuery query) {
return service.search(limit, query);
}
}
I know the example is a little stupid but the point of this post is Mockito, not the delegation.
SearchQuery
class is from a third party library and guess what - it doesn’t
have equals()
method! It is important because Mockito uses equals
method of
SearchQuery
class to associate actual calls with mocks. In this setup,
service.search
line will return null
because two instances of SearchQuery
are not the same. The assertion fails, verification fails.
To make this example working, let’s change the test setup as follows:
@Test
public void mockTest() {
SearchQuery mockQuery = Mockito.mock(SearchQuery.class);
UserService mockService = Mockito.mock(UserService.class);
Mockito.when(mockService.search(10, mockQuery)).thenReturn(testUser);
User actual = new UserSearcher(mockService).search(10, mockQuery);
assertEquals(testUser, actual);
Mockito.verify(mockService).search(10, mockQuery); //passes
}
So we created a mock of SearchQuery
class and passed it to when
method,
also to delegator, and verifier. This method registers the mock,
service.search
returns testUser
now! Also it allows you to test other
arguments directly(in this example limit
). If you want to verify an exact
query method is passed in the service.search
method call, you can verify
setters of SearchQuery
class (if there is any, just assumption). Here is an
example:
@Test
public void mockTest() {
// ... other tests
Mockito.verify(mockService).search(10, mockQuery);
Mockito.verify(mockQuery).setName("tarik");
Mockito.verify(mockQuery).setSurname("yurt");
Mockito.verifyNoMoreInteractions(mockQuery);
}
By typing these lines, we verified the exact query instance is built and passed
to UserService::search
method.