java - Mockito. Verify method arguments

ID : 10388

viewed : 45

Tags : javaunit-testingjunitmockitojava

Top 5 Answer for java - Mockito. Verify method arguments

vote vote

98

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()); } 
vote vote

82

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.

vote vote

80

argThat plus lambda

that 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 asserts

the 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

  • THE CALL IS EXPECTED 1 TIME, or
  • the call is expected 2+ times, but all the times the verifier matches (returns 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.


direct argument

Mokito compares direct arguments using equals():

verify(mock).mymethod(expectedArg); // NOTE:   ^ where the parentheses must be closed. 

eq matcher


argThat 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).*
vote vote

60

  • You don't need the eq matcher if you don't use other matchers.
  • You are not using the correct syntax - your method call should be outside the .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"); 
vote vote

59

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     } } 

Top 3 video Explaining java - Mockito. Verify method arguments

Related QUESTION?