355

I'm trying to test some legacy code, using Mockito.

I want to stub a FooDao that is used in production as follows:

foo = fooDao.getBar(new Bazoo());

I can write:

when(fooDao.getBar(new Bazoo())).thenReturn(myFoo);

But the obvious problem is that getBar() is never called with the same Bazoo object that I stubbed the method for. (Curse that new operator!)

I would love it if I could stub the method in a way that it returns myFoo regardless of the argument. Failing that, I'll listen to other workaround suggestions, but I'd really like to avoid changing the production code until there is reasonable test coverage.

Eric Wilson
  • 57,719
  • 77
  • 200
  • 270

4 Answers4

531
when(
  fooDao.getBar(
    any(Bazoo.class)
  )
).thenReturn(myFoo);

or (to avoid nulls):

when(
  fooDao.getBar(
    (Bazoo)notNull()
  )
).thenReturn(myFoo);

Don't forget to import matchers (many others are available):

For Mockito 2.1.0 and newer:

import static org.mockito.ArgumentMatchers.*;

For older versions:

import static org.mockito.Matchers.*;
Yarek T
  • 9,715
  • 2
  • 28
  • 38
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • 2
    I love it when the answer precedes the end of the 'accept answer freeze'. – Eric Wilson May 11 '11 at 19:50
  • 11
    There's a `notNull(Bazoo.class)` just like the `any(Bazoo.class)` (maybe it didn't exist at the time of this answer) – Dandre Allison Feb 20 '13 at 22:07
  • 2
    i had a slightly special situation where i could have either of two possible arguments - `Bazoo` or `Cazoo` which are both subclasses of, say, `Azoo`. for `Bazoo` i needed to return `foo`, but for `Cazoo` i needed to return `bar`. in this situation the proposed `Matchers.any()` solution doesn't work, however, `Matchers.isA()` works perfect. – Tanvir Apr 15 '14 at 14:57
  • 3
    `org.mockito.Matchers` is now deprecated - use `org.mockito.ArgumentMatchers` instead, i.e. `import static org.mockito.ArgumentMatchers.*` (see [docs](https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Matchers.html)) – DontDivideByZero Nov 01 '17 at 13:38
  • `when(myFoo.knowsWhatsUp()).thenReturn(myMoney);` – 6rchid Jan 29 '19 at 23:43
  • For some reason I do not understand, in my case Eclipse only imports the `any` method from the `CoreMatchers` package. I had to manually add the import statement from the `ArgumentMatchers` package. – luca.vercelli May 13 '20 at 09:49
24

http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Matchers.html

anyObject() should fit your needs.

Also, you can always consider implementing hashCode() and equals() for the Bazoo class. This would make your code example work the way you want.

Ihor Patsian
  • 1,288
  • 2
  • 15
  • 25
Buhb
  • 7,088
  • 3
  • 24
  • 38
  • Agreed with second suggestion, but I'm still opting to not do that for non-technical reasons. – Eric Wilson May 11 '11 at 19:46
  • 2
    The Matchers class is deprecated (see [docs](https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Matchers.html) - _"This class will likely be removed in version 3.0"_) – Johannes Rabauer Oct 10 '19 at 06:52
  • @JohannesRabauer I guess it should be changed to `any()` ? – golimar May 04 '21 at 09:19
  • @golimar it looks like this does the exact same thing. `any()` and `anyObject()` are the same, according to the docs linked above. However the complete `Matchers` class is deprecated and the class `ArgumentMatchers` should be used instead. – Johannes Rabauer Sep 13 '21 at 13:42
18

Use like this:

when(
  fooDao.getBar(
    Matchers.<Bazoo>any()
  )
).thenReturn(myFoo);

Before you need to import Mockito.Matchers

Hamad
  • 5,096
  • 13
  • 37
  • 65
5

Another option is to rely on good old fashion equals method. As long as the argument in the when mock equals the argument in the code being tested, then Mockito will match the mock.

Here is an example.

public class MyPojo {

    public MyPojo( String someField ) {
        this.someField = someField;
    }

    private String someField;

    @Override
    public boolean equals( Object o ) {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;
        MyPojo myPojo = ( MyPojo ) o;
        return someField.equals( myPojo.someField );
    }

}

then, assuming you know what the value for someField will be, you can mock it like this.

when(fooDao.getBar(new MyPojo(expectedSomeField))).thenReturn(myFoo);

pros: This is more explicit then any matchers. As a reviewer of code, I keep an eye open for any in the code junior developers write, as it glances over their code's logic to generate the appropriate object being passed.

con: Sometimes the field being passed to the object is a random ID. For this case you cannot easily construct the expected argument object in your mock code.

Another possible approach is to use Mockito's Answer object that can be used with the when method. Answer lets you intercept the actual call and inspect the input argument and return a mock object. In the example below I am using any to catch any request to the method being mocked. But then in the Answer lambda, I can further inspect the Bazo argument... maybe to verify that a proper ID was passed to it. I prefer this over any by itself so that at least some inspection is done on the argument.

    Bar mockBar = //generate mock Bar.

    when(fooDao.getBar(any(Bazo.class))
    .thenAnswer(  ( InvocationOnMock invocationOnMock) -> {
        Bazo actualBazo = invocationOnMock.getArgument( 0 );

        //inspect the actualBazo here and thrw exception if it does not meet your testing requirements.
        return mockBar;
    } );

So to sum it all up, I like relying on equals (where the expected argument and actual argument should be equal to each other) and if equals is not possible (due to not being able to predict the actual argument's state), I'll resort to Answer to inspect the argument.

Jose Martinez
  • 11,452
  • 7
  • 53
  • 68