[java] Mockito. Verify method arguments

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.

This question is related to java unit-testing junit mockito

The answer is


Verify(a).aFunc(eq(b))

In pseudocode:

When in the instance a - a function named aFunc is called.

Verify this call got an argument which is equal to b.


Many of the above answers confused me but I suspect it may be due to older versions of Mockito. This answer is accomplished using

  • Java 11
  • Mockito 3.1.0
  • SpringBoot 2.2.7.RELEASE
  • JUnit5

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

  • 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");

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)));

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.


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.


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.


argThat with multiple arguments.

If you use argThat, all arguments must be provided with matches. E.g.:

    verify(mock).mymethod(eq("VALUE_1"), argThat((x)->false));
    // above is correct as eq() is also an argument matcher.

verify(mock).mymethod("VALUE_1", argThat((x)->false));

// above is incorrect; an exceptoin will be thrown, as the fist 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;

eq matcher

the easiest way to check if the argument is equal:

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

direct argument

if comparison by ref is acceptable, then go on with:

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

THE ROOT CAUSE of original question failure was the wrong place of the paranthes: verify(mock.mymethod.... That was wrong. The right would be: verify(mock).*


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.


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

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

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)));

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to unit-testing

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0 How to test the type of a thrown exception in Jest Unit Tests not discovered in Visual Studio 2017 Class Not Found: Empty Test Suite in IntelliJ Angular 2 Unit Tests: Cannot find name 'describe' Enzyme - How to access and set <input> value? Mocking HttpClient in unit tests Example of Mockito's argumentCaptor How to write unit testing for Angular / TypeScript for private methods with Jasmine Why is the Visual Studio 2015/2017/2019 Test Runner not discovering my xUnit v2 tests

Examples related to junit

Eclipse No tests found using JUnit 5 caused by NoClassDefFoundError for LauncherFactory How to resolve Unneccessary Stubbing exception JUnit 5: How to assert an exception is thrown? How do I mock a REST template exchange? Class Not Found: Empty Test Suite in IntelliJ Unable to find a @SpringBootConfiguration when doing a JpaTest Failed to load ApplicationContext (with annotation) Example of Mockito's argumentCaptor Mockito - NullpointerException when stubbing Method Spring jUnit Testing properties file

Examples related to mockito

How to resolve Unneccessary Stubbing exception How do I mock a REST template exchange? Mockito : doAnswer Vs thenReturn Example of Mockito's argumentCaptor Mockito: Mock private field initialization Mockito - NullpointerException when stubbing Method Usages of doThrow() doAnswer() doNothing() and doReturn() in mockito Java verify void method calls n times with Mockito Unfinished Stubbing Detected in Mockito How do I mock an autowired @Value field in Spring with Mockito?