Assert Mockito mock method arguments if no equals() method implemented
Mock JUnit tests with Mockito example post introduces Mockito as Java mocking framework. The code shown in examples below is available in GitHub java-samples/junit repository. Mockito makes it possible to verify whether a mock method has been called and with what specific object:
verify(locatorServiceMock, times(1)).geoLocate(new Point(1, 1));
The code above verifies that mock’s geoLocate() method was called with argument object with coordinates (1, 1).
Missing equals() method
Internally Mockito uses Point class's equals() method to compare object that has been passed to the method as an argument with object configured as expected in verify() method. If equals() is not overridden then java.lang.Object's equals() is used which compares only the references, i.e. if both variables point to one and the same object in heap. In the current example, Point class has no equals() method implemented. When providing expected a new object is created, references are not one and the same, so Mockito will fail the verification.Override equals()
In order to make verification works simplest solution is to implement equals() method in Point class. Personally, I'm not a big fan of changing production code for sake of testing. Maybe there is a valid reason for a developer to have designed current class in such manner. A more realistic scenario is that Point class comes from some external library which there is no control over, so overriding equals() method is not possible at all.Use Mockito argThat matcher
Mockito provides a method called argThat() in org.mockito.Matchers class. It accepts an object from the class that implements org.hamcrest.Matcher<T> interface. Actual equals implementation is done in its matches() method:private class PointMatcher extends ArgumentMatcher<Point> {
private final Point expected;
public PointMatcher(Point expected) {
this.expected = expected;
}
@Override
public boolean matches(Object obj) {
if (!(obj instanceof Point)) {
return false;
}
Point actual = (Point) obj;
return actual.getX() == expected.getX()
&& actual.getY() == expected.getY();
}
}
Once implemented this class can be used in tests:
verify(locatorServiceMock, times(1))
.geoLocate(argThat(new PointMatcher(new Point(1, 1))));