Reputation: 6982
I've googled about this, but didn't find anything relevant. I've got something like this:
Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj )).thenReturn(null);
Testeable testableObj = new Testeable();
testableObj.setMockeable(mock);
command.runtestmethod();
Now, I want to verify that mymethod(Object o)
, which is called inside runtestmethod()
, was called with the Object o
, not any other. But I always pass the test, whatever I put on the verification, for example, with:
Mockito.verify(mock.mymethod(Mockito.eq(obj)));
or
Mockito.verify(mock.mymethod(Mockito.eq(null)));
or
Mockito.verify(mock.mymethod(Mockito.eq("something_else")));
I always pass the test. How can I accomplish that verification (if possible)?
Thank you.
Upvotes: 389
Views: 503046
Reputation: 225
All the answers seem confusing to me, so here is what is working for me on Java 8 -
verify(myClass, times(<howManyTimes>)).myMehtod(<expectedValue1>, <expectedValue2>, ...and so on);
Upvotes: 0
Reputation: 10978
argThat
plus lambdathat is how you can fail your argument verification:
verify(mock).mymethod(argThat(
x -> false ));
where
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
argThat
plus assertsthe above test will "say" Expected: lambda$... Was: YourClass.toSting...
. You can get a more specific cause of the failure if to use asserts in the the lambda:
verify(mock).mymethod(argThat( x -> {
assertThat(x).isNotNull();
assertThat(x.description).contains("KEY");
return true;
}));
❗️BUT❗️: THIS ONLY WORKS WHEN
true
).If the verified method called 2+ times, mockito passes all the called combinations to each verifier. So mockito expects your verifier silently returns true
for one of the argument set, and false
(no assert exceptions) for other valid calls. That expectation is not a problem for 1 method call - it should just return true 1 time.
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
Now the failed test will say: Expected: Obj.description to contain 'KEY'. Was: 'Actual description'
. NOTE: I used assertJ
asserts, but it's up to you which assertion framework to use.
Mokito compares direct arguments using equals()
:
verify(mock).mymethod(expectedArg);
// NOTE: ^ where the parentheses must be closed.
eq
matchereq
for a single arg. Use the aforementioned direct argument.equals()
eq
would be a SonarQube / SonarClound violation: https://rules.sonarsource.com/java/tag/mockito/RSPEC-6068argThat
with multiple arguments.If you use argThat
, all arguments must be provided with matches. E.g. if, in a different case, you had another method with 2 arguments:
verify(mock).mymethod2(eq("VALUE_1"), argThat((x)->false));
// above is correct as eq() is also an argument matcher.
verify(mock).mymethod2("VALUE_1", argThat((x)->false));
// above is incorrect; an exception will be thrown, as the first arg. is given without an argument matcher.
where:
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
THE ROOT CAUSE of original question failure was the wrong place of the parentheses:
verify(mock.mymethod...
. That was wrong. The right would be:verify(mock).*
Upvotes: 146
Reputation: 434
Many of the above answers confused me but I suspect it may be due to older versions of Mockito. This answer is accomplished using
Using ArgumentCaptor I have done it this way:
@Mock
MyClientService myClientService;
@InjectMocks
MyService myService;
@Test
void myTest() {
ArgumentCaptor<String> captorParam1 = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> captorParam2 = ArgumentCaptor.forClass(String.class);
Mockito.when(myClientService.doSomething(captorParam1.capture(), captorParam2.capture(), ArgumentMatchers.anyString()))
.thenReturn(expectedResponse);
assertDoesNotThrow(() -> myService.process(data));
assertEquals("param1", captorParam1.getValue());
assertEquals("param2", captorParam2.getValue());
verify(myClientService, times(1))
.doSomething(anyString(), anyString(), anyString());
}
Upvotes: 4
Reputation: 106
Verify(a).aFunc(eq(b))
In pseudocode:
When in the instance
a
- a function namedaFunc
is called.Verify this call got an argument which is equal to
b
.
Upvotes: 3
Reputation: 5430
I have used Mockito.verify in this way
@UnitTest
public class JUnitServiceTest
{
@Mock
private MyCustomService myCustomService;
@Test
public void testVerifyMethod()
{
Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0))
Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times
Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time
Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times
Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times
Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); // no other method called except this
}
}
Upvotes: 15
Reputation: 11304
You can also use TypeSafeDiagnosingMatcher
private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) {
return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() {
StringBuilder text = new StringBuilder(500);
@Override
protected boolean matchesSafely(GetPackagesRequest req, Description desc) {
String productCode = req.getPackageIds().iterator().next().getValue();
if (productCode.equals(request.getSupplierProductCode())) {
text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode());
return true;
}
text.append(req.toString());
return false;
}
@Override
public void describeTo(Description d) {
d.appendText(text.toString());
}
};
}
Then verify that invocation:
Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
Upvotes: 0
Reputation: 8842
An alternative to ArgumentMatcher
is ArgumentCaptor
.
Official example:
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());
A captor can also be defined using the @Captor annotation:
@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
//...
verify(mock).doSomething(captor.capture());
assertEquals("John", captor.getValue().getName());
}
Upvotes: 553
Reputation: 584
The other method is to use the org.mockito.internal.matchers.Equals.Equals method instead of redefining one :
verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));
Upvotes: 4
Reputation: 479
Have you tried it with the same() matcher? As in:
verify(mockObj).someMethod(same(specificInstance));
I had the same problem. I tried it with the eq() matcher as well as the refEq() matcher but I always had false positives. When I used the same() matcher, the test failed when the arguments were different instances and passed once the arguments were the same instance.
Upvotes: 3
Reputation: 4208
Are you trying to do logical equality utilizing the object's .equals method? You can do this utilizing the argThat matcher that is included in Mockito
import static org.mockito.Matchers.argThat
Next you can implement your own argument matcher that will defer to each objects .equals method
private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> {
T thisObject;
public ObjectEqualityArgumentMatcher(T thisObject) {
this.thisObject = thisObject;
}
@Override
public boolean matches(Object argument) {
return thisObject.equals(argument);
}
}
Now using your code you can update it to read...
Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj)).thenReturn(null);
Testeable obj = new Testeable();
obj.setMockeable(mock);
command.runtestmethod();
verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj)));
If you are just going for EXACT equality (same object in memory), just do
verify(mock).mymethod(obj);
This will verify it was called once.
Upvotes: 75
Reputation: 2308
Have you checked the equals method for the mockable class? If this one returns always true or you test the same instance against the same instance and the equal method is not overwritten (and therefor only checks against the references), then it returns true.
Upvotes: 5
Reputation: 597392
eq
matcher if you don't use other matchers..verify(mock)
. You are now initiating verification on the result of the method call, without verifying anything (not making a method call). Hence all tests are passing.You code should look like:
Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");
Upvotes: 63