Hot questions for Using Mockito in stub

Question:

I am getting following exception while running the tests. I am using Mockito for mocking. The hints mentioned by Mockito library are not helping.

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
    -> at com.a.b.DomainTestFactory.myTest(DomainTestFactory.java:355)

    E.g. thenReturn() may be missing.
    Examples of correct stubbing:
        when(mock.isOk()).thenReturn(true);
        when(mock.isOk()).thenThrow(exception);
        doThrow(exception).when(mock).someVoidMethod();
    Hints:
     1. missing thenReturn()
     2. you are trying to stub a final method, you naughty developer!

        at a.b.DomainTestFactory.myTest(DomainTestFactory.java:276)
        ..........

Test Code from DomainTestFactory. When I run the following test, I see the exception.

@Test
public myTest(){
    MyMainModel mainModel =  Mockito.mock(MyMainModel.class);
    Mockito.when(mainModel.getList()).thenReturn(getSomeList()); // Line 355
}

private List<SomeModel> getSomeList() {
    SomeModel model = Mockito.mock(SomeModel.class);
    Mockito.when(model.getName()).thenReturn("SomeName"); // Line 276
    Mockito.when(model.getAddress()).thenReturn("Address");
    return Arrays.asList(model);
}

public class SomeModel extends SomeInputModel{
    protected String address;
    protected List<SomeClass> properties;

    public SomeModel() {
        this.Properties = new java.util.ArrayList<SomeClass>(); 
    }

    public String getAddress() {
        return this.address;
    }

}

public class SomeInputModel{

    public NetworkInputModel() {
        this.Properties = new java.util.ArrayList<SomeClass>(); 
    }

    protected String Name;
    protected List<SomeClass> properties;

    public String getName() {
        return this.Name;
    }

    public void setName(String value) {
        this.Name = value;
    }
}

Answer:

You're nesting mocking inside of mocking. You're calling getSomeList(), which does some mocking, before you've finished the mocking for MyMainModel. Mockito doesn't like it when you do this.

Replace

@Test
public myTest(){
    MyMainModel mainModel =  Mockito.mock(MyMainModel.class);
    Mockito.when(mainModel.getList()).thenReturn(getSomeList()); --> Line 355
}

with

@Test
public myTest(){
    MyMainModel mainModel =  Mockito.mock(MyMainModel.class);
    List<SomeModel> someModelList = getSomeList();
    Mockito.when(mainModel.getList()).thenReturn(someModelList);
}

To understand why this causes a problem, you need to know a little about how Mockito works, and also be aware in what order expressions and statements are evaluated in Java.

Mockito can't read your source code, so in order to figure out what you are asking it to do, it relies a lot on static state. When you call a method on a mock object, Mockito records the details of the call in an internal list of invocations. The when method reads the last of these invocations off the list and records this invocation in the OngoingStubbing object it returns.

The line

Mockito.when(mainModel.getList()).thenReturn(someModelList);

causes the following interactions with Mockito:

  • Mock method mainModel.getList() is called,
  • Static method when is called,
  • Method thenReturn is called on the OngoingStubbing object returned by the when method.

The thenReturn method can then instruct the mock it received via the OngoingStubbing method to handle any suitable call to the getList method to return someModelList.

In fact, as Mockito can't see your code, you can also write your mocking as follows:

mainModel.getList();
Mockito.when((List<SomeModel>)null).thenReturn(someModelList);

This style is somewhat less clear to read, especially since in this case the null has to be casted, but it generates the same sequence of interactions with Mockito and will achieve the same result as the line above.

However, the line

Mockito.when(mainModel.getList()).thenReturn(getSomeList());

causes the following interactions with Mockito:

  1. Mock method mainModel.getList() is called,
  2. Static method when is called,
  3. A new mock of SomeModel is created (inside getSomeList()),
  4. Mock method model.getName() is called,

At this point Mockito gets confused. It thought you were mocking mainModel.getList(), but now you're telling it you want to mock the model.getName() method. To Mockito, it looks like you're doing the following:

when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);

This looks silly to Mockito as it can't be sure what you're doing with mainModel.getList().

Note that we did not get to the thenReturn method call, as the JVM needs to evaluate the parameters to this method before it can call the method. In this case, this means calling the getSomeList() method.

Generally it is a bad design decision to rely on static state, as Mockito does, because it can lead to cases where the Principle of Least Astonishment is violated. However, Mockito's design does make for clear and expressive mocking, even if it leads to astonishment sometimes.

Finally, recent versions of Mockito add an extra line to the error message above. This extra line indicates you may be in the same situation as this question:

3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

Question:

So I started writing tests for our Java-Spring-project.

What I use is JUnit and Mockito. It's said, that when I use the when()...thenReturn() option I can mock services, without simulating them or so. So what I want to do is, to set:

when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)  

But no matter which when-clause I do, I always get a NullpointerException, which of course makes sense, because input is null.

Also when I try to mock another method from an object:

when(object.method()).thenReturn(true)

There I also get a Nullpointer, because the method needs a variable, which isn't set.

But I want to use when()..thenReturn() to get around creating this variable and so on. I just want to make sure, that if any class calls this method, then no matter what, just return true or the list above.

Is it a basically misunderstanding from my side, or is there something else wrong?

Code:

public class classIWantToTest implements classIWantToTestFacade{
        @Autowired
        private SomeService myService;

        @Override
        public Optional<OutputData> getInformations(final InputData inputData) {
            final Optional<OutputData> data = myService.getListWithData(inputData);
            if (data.isPresent()) {
                final List<ItemData> allData = data.get().getItemDatas();
                    //do something with the data and allData
                return data;
            }

            return Optional.absent();
        }   
}

And here is my test class:

public class Test {

    private InputData inputdata;

    private ClassUnderTest classUnderTest;

    final List<ItemData> allData = new ArrayList<ItemData>();

    @Mock
    private DeliveryItemData item1;

    @Mock
    private DeliveryItemData item2;



    @Mock
    private SomeService myService;


    @Before
    public void setUp() throws Exception {
        classUnderTest = new ClassUnderTest();
        myService = mock(myService.class); 
        classUnderTest.setService(myService);
        item1 = mock(DeliveryItemData.class);
        item2 = mock(DeliveryItemData.class);

    }


    @Test
    public void test_sort() {
        createData();
        when(myService.getListWithData(inputdata).get().getItemDatas());

        when(item1.hasSomething()).thenReturn(true);
        when(item2.hasSomething()).thenReturn(false);

    }

    public void createData() {
        item1.setSomeValue("val");
        item2.setSomeOtherValue("test");

        item2.setSomeValue("val");
        item2.setSomeOtherValue("value");

        allData.add(item1);
        allData.add(item2);


}

Answer:

I had this issue and my problem was that I was calling my method with any() instead of anyInt(). So I had:

doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())

and I had to change it to:

doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())

I have no idea why that produced a NullPointerException. Maybe this will help the next poor soul.

Question:

I am getting following error when stubbing a void:

The method when(T) in the type Stubber is not applicable for the arguments (void)

Here is my sample code:

doNothing().when(mockRegistrationPeristImpl.create(any(Registration.class)));

public void create(final T record) throws DataAccessException {
    try {
        entityManager.persist(record);
        entityManager.flush();
    } catch (PersistenceException ex) {}
}

What am I missing ?


Answer:

Your brackets are in the wrong place, try this:

doNothing().when(mockRegistrationPeristImpl).create(any(Registration.class));

Question:

I want to stub a repository class to test another class (Holder class) that has a repository. The repository interface supports CRUD operations, and has many methods, but my unit test on the Holder class only needs to call two of them. The repository interface:

public interface IRepo {
    public void remove(String... sarr);

    public void add(String... sarr);

    //Lots of other methods I don't need now
}

I want to create a repository mock that can store instances, define logic for add and remove only, and also provide a means of checking what is stored on it after calling add and remove.

If I do:

IRepo repoMock = mock(IRepo.class);

Then I have a dumb object that does nothing on each method. That's OK, now I just need to define behaviour for add and remove.

I could create a Set<String> and stub only those two methods to work on the set. Then I'd instantiate a Holder that has an IRepo, inject the partially stubbed mock, and after exercising the holder, check the set to verify it contains what it should.

I've managed to partially stub a void method like remove using the deprecated method stubVoid:

Set<String> mySet = new HashSet<>();
stubVoid(repoMock).toAnswer(new Answer<Void>() {

    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        String[] stringsToDelete = (String[]) args[0];
        mySet.removeAll(Arrays.asList(stringsToDelete));
        return null;
    }
}).on().remove(Matchers.<String>anyVararg());

But is deprecated, and it is not much better than creating a partial implementation for IRepo. Is there a better way?

NOTE: Java 7 answers only please, this should run in Android.


Answer:

You can use

  Mockito.doAnswer(new Answer<Void>() {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            //DO SOMETHING
            return null;
        }
    }).when(...).remove(Matchers.<String>anyVararg());

From the Javadoc:

Use doAnswer() when you want to stub a void method with generic Answer.

Stubbing voids requires different approach from Mockito.when(Object) because the compiler does not like void methods inside brackets...

Example:

    doAnswer(new Answer() {
    public Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        Mock mock = invocation.getMock();
        return null;
    }}).when(mock).someMethod();

See examples in javadoc for Mockito

Question:

I try to simulate the behaviour of a class, using Mockito. This worked using Mockito 1.x. Migrating to JUnit 5 and Mockito 2 it seems not to work anymore.

@ExtendWith(MockitoExtension.class)
public class MockitoExample {

  static abstract class TestClass {
    public abstract int booleanMethod(boolean arg);
  }

  @Mock
  TestClass testClass;

  @BeforeEach
  public void beforeEach() {
    when(testClass.booleanMethod(eq(true))).thenReturn(1);
    when(testClass.booleanMethod(eq(false))).thenReturn(2);
  }

  @Test
  public void test() {
    assertEquals(1,testClass.booleanMethod(true));
    assertEquals(2,testClass.booleanMethod(false));
  }
}

The expectation is, that the mocked TestClass shows the behaviour as tested in the test-method.

The error I get is:

org.mockito.exceptions.misusing.PotentialStubbingProblem: 

  Strict stubbing argument mismatch. Please check:
   - this invocation of 'booleanMethod' method:
      testClass.booleanMethod(false);
      -> at org.oneandone.ejbcdiunit.mockito_example.MockitoExample.beforeEach(MockitoExample.java:30)
   - has following stubbing(s) with different arguments:
      1. testClass.booleanMethod(false);
        -> at org.oneandone.ejbcdiunit.mockito_example.MockitoExample.beforeEach(MockitoExample.java:29)
  Typically, stubbing argument mismatch indicates user mistake when writing tests.
  Mockito fails early so that you can debug potential problem easily.
  However, there are legit scenarios when this exception generates false negative signal:
    - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
      Please use 'will().given()' or 'doReturn().when()' API for stubbing.
    - stubbed method is intentionally invoked with different arguments by code under test
      Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
  For more information see javadoc for PotentialStubbingProblem class.

In both cases, the argument false seems to be matched, though I clearly matched with true.

Is that a bug in Mockito 2.17 or a misunderstanding. How should/can I use Mockito 2.x to simulate calls with different boolean arguments?

The example can also be found on github. But surefire will start the test only using

mvn test -Dtest=MockitoExample

Executing the test using Mockito 2.21 leads to the same results.


Answer:

With strict stubs (the default behavior of Mockito) calling several whens on the same method will reset that mock. The solution is to call when once and have the logic in an Answer:

@BeforeEach
public void beforeEach() {
    when(testClass.booleanMethod(anyBoolean())).thenAnswer(invocationOnMock -> {
        if ((boolean) invocationOnMock.getArguments()[0]) {
            return 1;
        }
        return 2;
    });
}

Alternatively, you can use lenient mocking, but that's not always a good idea - lenient mocking allows redundant stubbing, and makes it easier for you to make mistakes in your test, which may lead to unnoticed bugs in the "production" code:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class MockitoExample {

Question:

I am wondering if there is anyway to stub the value of Build.Version.SDK_INT? Suppose I have the following lines in the ClassUnderTest:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    //do work
}else{
    //do another work
}

How can I cover all the code ?

I mean I want to run two tests with different SDK_INT to enter both blocks.

Is it possible in android local unit tests using Mockito/PowerMockito?

Thanks


Answer:

Change the value using reflection.

 static void setFinalStatic(Field field, Object newValue) throws Exception {
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    field.set(null, newValue);
 }

And then

 setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 123);

It is tested. Works.

Update: There is a cleaner way to do it.

Create an interface

interface BuildVersionProvider {

    fun currentVersion(): Int

}

Implement the interface

class BuildVersionProviderImpl : BuildVersionProvider {

    override fun currentVersion() = Build.VERSION.SDK_INT

}

Inject this class as a constructor argument through the interface whenever you want current build version. Then in the tests when creating a SUT (System Under Test) object. You can implement the interface yourself. This way of doing things may be more code but follows the SOLID principles and gives you testable code without messing with reflection and system variables.

Question:

I'm trying to use the Mockito deep stubbing feature with the doReturn method.

When I use the when method as in the deep stubbing example it works fine:

Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
when(mock.getBar().getName()).thenReturn("deep");

But when I try then same thing with doReturn I get a WrongTypeOfReturnValue:

doReturn("deep").when(mock).getBar().getName();

I have also tried it these ways but then I get an UnfinishedStubbingException:

doReturn("deep").when(mock.getBar()).getName();
doReturn("deep").when(mock.getBar().getName());

How can I use the deep stubbing feature with the doReturn method?

(I am aware that the use of deep stubbing is discouraged by some, including the Mockito developers. I'm not sure if I agree with their position on this. Let's keep that discussion out of this issue.)


Answer:

It seems Mockito gets confused when you call your deep stub in then when method. I was able to work around it by calling mock.getBar() separately:

    Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
    Bar bar = mock.getBar();
    doReturn("deep").when(bar).getName();

Question:

I'm using Mockito for unit testingand I'm getting the following exception.

org.mockito.exceptions.base.MockitoException: 
`'setResponseTimeStampUtc'` is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
    doThrow(exception).when(mock).someVoidMethod();
***

If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.
2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.
3. A spy is stubbed using `when(spy.foo()).then()` syntax. It is safer to stub spies - 
   - with `doReturn|Throw()` family of methods. More in javadocs for Mockito.spy() method.

Here is the actual class

@Repository
public class CardRepositoryImpl implements ICardRepository {        
    @Autowired
    private OperationBean operation;

    @Override
    public OperationBean getCardOperation(final String cardHolderId, final String requestTimeStamp) {
        operation.setRequestTimeStampUtc(requestTimeStamp);
        operation.setResponseTimeStampUtc(DateUtil.getUTCDate());
        return operation;
    }
}

this is the Test class I have written.

@RunWith(MockitoJUnitRunner.class)
public class CardRepositoryImplUnitTestFixture_Mockito {
    @InjectMocks
    private CardRepositoryImpl cardRepositoryImpl;
    private OperationBean operationBean;

    @Before
    public void beforeTest() {
        MockitoAnnotations.initMocks(this);
    }
    @Test
    public void canGetCardOperation(){
        when(cardRepositoryImpl.getCardOperation("2", Mockito.anyString())).thenReturn(operationBean);

    }    
}

Is this an issue with the return statement since format() method is a final method.

public static String getUTCDate() {
    final TimeZone timeZone = TimeZone.getTimeZone("UTC");
    final Calendar calendar = Calendar.getInstance(timeZone);
    final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd'T'HH:mm:ss.SSS'Z'");
    simpleDateFormat.setTimeZone(timeZone);
    return simpleDateFormat.format(calendar.getTime());
}

How can I resolve this?


Answer:

@InjectMocks
private CardRepositoryImpl cardRepositoryImpl;

when(cardRepositoryImpl.getCardOperation("2", Mockito.anyString()))
    .thenReturn(operationBean);

cardRepositoryImpl is not a mock, so you can't stub it. With @InjectMocks you are instructing Mockito to construct a real CardRepositoryImpl and have its private fields and constructor parameters substituted with fields on the test case. You'll probably want to use a spy instead; more on that in a second.

But first, why that error message? Because it's not a mock, the call to cardRepositoryImpl.getCardOperation happens on an actual CardRepositoryImpl instance. Mockito sees the interactions with operationBean (which does seem to be a mock), treats the when and thenReturn as corresponding with that most recent mock call, and erroneously tells you you're stubbing a void method (importantly, the wrong method) with a return value.


In a test for CardRepositoryImpl, you shouldn't be mocking CardRepositoryImpl, nor stubbing it to return values: This won't test anything, except that Mockito works. You should probably rethink what you need to stub in order for your test to work.

However, when stubbing one method, you might want to stub another method in the same class. This can be accomplished with a spy:

@Test
public void canGetCardOperation(){
    CardRepositoryImpl spyImpl = spy(cardRepositoryImpl);
    when(spyImpl.getCardOperation(Mockito.eq("2"), Mockito.anyString()))
        .thenReturn(returnValue);
    // ...
    spyImpl.someOtherMethod();  // Any matching calls to getCardOperation from
                                // someOtherMethod will use the stub above.
}

Side note: You use anyString and "2" adjacently while stubbing. When using Matchers like anyString, you need to use them for all arguments if you use them for any arguments at all. See more here.

Question:

Say we have java class called SomeClass

public class SomeClass {

    private boolean isMethod() {

        return false;
    }

    public void sendRequest(String json, String text) {

        int messageId;

        if (isMethod()) {
            messageId = getMessageId(json);
            sendMessage(messageId, text);
        } else {
            throw new IllegalArgumentException();
        }
    }

    private void sendMessage(int messageId, String text) {

    }

    private int getMessageId(String text) {

        Pattern p = Pattern.compile("messageId=(\\d+)&");
        Matcher m = p.matcher(text);

        if (m.find()) {
            return Integer.valueOf(m.group(1));
        }
        return 0;
    }
}

Don't pay attention to methods' name, they're all optional.

  • I want to test sendRequest(String json, String text) method in isolation.
  • I want to stub methods isMethod() and getMessageId(json), and verify that sendMessage(messageId, text) method is called.
  • I need to be sure that getMessageId(json) returns 25 and that isMethod() returns true no matter which argument value given.

Answer:

This could be achieved by PowerMockito framework.

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {

    private SomeClass someInstance;

    @Before
    public void setUp() throws Exception {

        someInstance = PowerMockito.spy(new SomeClass());
    }

    @Test
    public void sendRequest() throws Exception {

        String json = "JSON";
        String text = "Some text";
        int messageId = 1;

        PowerMockito.doReturn(true).when(someInstance, "isMethod");
        PowerMockito.doReturn(messageId).when(someInstance, "getMessageId", json);

        someInstance.sendRequest(json, text);

        PowerMockito.verifyPrivate(someInstance).invoke("isMethod");
        PowerMockito.verifyPrivate(someInstance).invoke("getMessageId", json);
        PowerMockito.verifyPrivate(someInstance).invoke("sendMessage", messageId, text);
    }

}

Question:

I've got a ThingsProvider interface I'm trying to test with Mockito, (simplified version) defined as follows:

interface ThingsProvider {
    Iterable<? extends Thing> getThings()
}

Now when I'm going to test it with Mockito, I'm doing the following (again, simplified for the question):

ThingsProvider thingsProvider = mock(ThingsProvider.class);
List<Thing> things = Arrays.asList(mock(Thing.class));
when(thingsProvider.getThings()).thenReturn(things); // PROBLEM IS HERE

Compile error message: The method thenReturn(Iterable<capture#11-of ? extends Thing>) in the type OngoingStubbing<Iterable<capture#11-of ? extends Thing>> is not applicable for the arguments (List<Thing>)

Now, purely for getting the test going, I'm changing the last line to

when(thingsProvider.getThings()).thenReturn((List)things); // HAHA take THAT generics!

... but this would clearly be bad to do in non-testing code.

My question(s):

  1. Why is this an error? I'm clearly returning objects that extend Thing, which is what the interface expects.
  2. Is there a better way of solving this? Perhaps defining my interface differently? I haven't run into this issue outside of testing so far...

On #2 - The main reason I'm not simply returning Iterable<Thing> is that there are several different extensions where the concrete types have things buried in them that return specific subtypes, and I end up with issues like Type mismatch: cannot convert from Iterable<MagicalThing> to Iterable<Thing> - maybe the solution is a better way to fix this issue?


For those of you less familiar with Mockito, a more pure Java version of #1 is below:

public static void main(String...args) {
    List<Integer> ints = Arrays.asList(1,2,3);
    blah(ints);

    Foo<Number> foo1 = new Foo<Number>();
    foo1.bar(ints);  // This works

    Foo<? extends Number> foo2 = new Foo<Number>();
    foo2.bar(ints);  // NO COMPILEY!
} 

private static void blah(List<? extends Number> numberList) {
    // something
}

public static class Foo<T> {
    public Object bar(List<? extends T> tList) {
        return null;
    }
}

Answer:

Wildcard in return type is very convenient for subclass implementations, as you've observed.

It doesn't make much difference to the callers of the method though; you may change it to Iterable<Thing> if you'd like to; it's simpler on javadoc, at the expense of subclass implementers. Subclass can do brute cast if necessary, e.g. List<MyThing> => Iterable<Thing>, thanks to erasure.


The reason for your problem is wildcard capture; basically every expression goes though wildcard capture first before the contextual expression is evaluated. In a method invocation

    foo( arg )

arg is always wildcard-captured first, before method applicability/overloading/inference are done. In your case, the more general type Iterable<? extends Thing> is lost, becomes Iterable<CAP#>.

Usually, wildcard capture does not pose any problem; but Mockito semantics is nothing usual.


The first solution is to avoid type inference; explicitly supply type arguments instead

Mockito.<Iterable<? extends Thing>>when(...

Or as Delimanolis suggested, use a target type to restrict inference (in java8+)

OngoingStubbing<Iterable<? extends Thing>> stub =  when(...

It also appears that lambda inference may be helpful for this case

static <T> OngoingStubbing<T> whenX( Supplier<T> sup )
{    
    return Mockito.when( sup.get() );
}

whenX(thingsProvider::getThings).thenReturn(things);
// T = Iterable<? extends Thing>

And - if your interface is simple enough, just directly implement it instead of mock it :)

List<Thing> things = ...;

ThingsProvider thingsProvider = ()->things;

Question:

Can any one explain what is ongoing Stubbing in mockito and how it helps writing in Junit Testcase and mocking the methods.


Answer:

OngoingStubbing is an interface that allows you to specify an action to take in response to a method call. You should never need to refer to OngoingStubbing directly; all calls to it should happen as chained method calls in the statement starting with when.

// Mockito.when returns an OngoingStubbing<String>,
// because foo.bar should return String.
when(foo.bar()).thenReturn("baz");

// Methods like thenReturn and thenThrow also allow return OngoingStubbing<T>,
// so you can chain as many actions together as you'd like.
when(foo.bar()).thenReturn("baz").thenThrow(new Exception());

Note that Mockito requires at least one call to an OngoingStubbing method, or else it will throw UnfinishedStubbingException. However, it doesn't know the stubbing is unfinished until the next time you interact with Mockito, so this can be the cause of very strange errors.

// BAD: This will throw UnfinishedStubbingException...
when(foo.bar());

yourTest.doSomething();

// ...but the failure will come down here when you next interact with Mockito.
when(foo.quux()).thenReturn(42);

Though it is technically possible to keep around a reference to an OngoingStubbing object, that behavior is not defined by Mockito, and is generally considered a very bad idea. This is because Mockito is stateful, and operates via side effects during stubbing.

// BAD: You can very easily get yourself in trouble this way.
OngoingStubbing stubber = when(foo.bar());
stubber = stubber.thenReturn("baz");
stubber = stubber.thenReturn("quux");

Question:

Trying to stub a class with 2 possible invocation/return paths using custom Matcher ... ran into an interest problem.

Here is a test I wrote to illustrate ...

This might be difficult to implement, but I would have expected the 1st ArgumentMatcher is not invoked when stubbing the second when(...).thenReturn(...)

But running the code below prints foobar on stdout. Is there anything we can do to prevent this behavior? Or am I using the wrong pattern by trying to stub a single mock with multiple custom ArgumentMatcher

FYI - powermock is on my classpath for other tests (not sure if that matters but I do see it in the stack trace)

import org.junit.Test;
import org.mockito.ArgumentMatcher;

import java.io.File;
import java.io.FilenameFilter;

import static org.mockito.Matchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class MyTest {
    @Test
    public void name() throws Exception {
        File file = mock(File.class);
        when(file.list(argThat(new ArgumentMatcher<FilenameFilter>() {
            @Override
            public boolean matches(Object argument) {
                System.out.println("foobar");
                return 1 + 1 >2;
            }
        }))).thenReturn(null);
        // at this point, mockito will attempt to run the previous matcher, treating this stub code as invocation ... and printing out 'foobar'
        when(file.list(argThat(new ArgumentMatcher<FilenameFilter>() {
            @Override
            public boolean matches(Object argument) {
                System.out.println("barbar");
                return true;
            }
        }))).thenReturn(null);

    }
}

EDIT added comments to help illustrate


Answer:

If you use the doReturn() syntax, then the method is not called.

doReturn(null).when(file).list(argThat(new ArgumentMatcher<FilenameFilter>() {
    @Override
    public boolean matches(Object argument) {
        System.out.println("barbar");
        return true;
    }
}));

See this answer for more details. Also, the docs explain this use-case (emphasis mine):

You can use doReturn(), [...] in place of the corresponding call with when(), for any method. It is necessary when you:

  • stub void methods
  • stub methods on spy objects (see below)
  • stub the same method more than once, to change the behaviour of a mock in the middle of a test.

Question:

Below MyDictionary.get method uses the injected map by calling map.get.

Just of curiosity I stubbed the MyDictionary.get method, like I always do with mocks and spies, so I overwrite the injection.

But this only works when MyDictionary.get indeed calls map.get. If map.get returns some string (the empty string here), the stub Mockito.when does not work. The behavior is as if it is not there. In the assert line, dictionary.get("key") equals the empty string. This is what I do not understand.

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {

    @Mock
    Map<String, String>map;

    @InjectMocks
    MyDictionary dictionary;

    @Test
    public void testMyDictionary(){
        Mockito.when(dictionary.get("key")).thenReturn("value");
        Assert.assertEquals("value", dictionary.get("key"));
    }

    private static class MyDictionary{
        private Map<String, String> map; 
        public String get(String key){
            return map.get(key);
// or,
            return "";
        }
    }
}

Answer:

I am really surprised that you do not get a MissingMethodInvocationException which is thrown when you try to stub a method of an object not being a @Mock or a @Spy.

The dictionary instance is just a regular instance of a class here not proxied by Mockito (because of the fact that only @InjectMocks annotation is used).

Another surprise is that you do not get a null when the map.get is triggered as default return value for a String returning method is null.

Anyway..

If you want to stub methods of the `dictionary' instance you have to configure your test class as follows:

@InjectMocks
@Spy
MyDictionary dictionary;

@Test
public void testMyDictionary(){
    doReturn("value").when(dictionary).get("key);
    Assert.assertEquals("value", dictionary.get("key"));
}

Question:

I have a class Dummy. I inject 3 variables. However, one of them is not injectable because it is an interface. So I inject an object, one of whose methods return the needed type.

Class Dummy
{
   private final Class1 class1;
   private final Class2 class2
   private final Interface1 interface1;

  @Inject
  Dummy(Class1 class1, Class2 class2, HelperClass helperclass) 
  {
       this.class1 = class1;
       this.class2 = class2;
       this.interface1 = helperclass.somefunction();
  }
}

The HelperClass's somefunction returns an instance of Interface1.

This is my test:

@RunWith(MockitoJUnitRunner.class)
Class DummyTest 
{
  @Mock 
  private Class1 class1;

  @Mock
  private Class2 class2;

  @Mock
  private HelperClass helperclass;

  @InjectMocks
  private Dummy dummy;

  @Before
  public void start() 
  {
    Interface1 mockInterface = mock(Interface1.class);
    when(helperclass.somefunction()).thenReturn(mockInterface);
  }
  @Test
  public void test()
  {
   // etc...
  }
}

However, interface1 is null when I run the test. What am I doing wrong?


Answer:

@InjectMocks happens before the @Before annotation.

For this reason (and other reasons), I recommend not using @InjectMocks at all; just build your SUT class in the @Before method with a real constructor.

This ordering is obvious when you add a few print statements to your test class. I removed all the Class1 and Class2 stuff as it's not relevant. See this code run:

@RunWith(MockitoJUnitRunner.class)
public class DummyTest {
  @Mock
  private HelperClass helperclass;

  @InjectMocks
  private Dummy dummy;

  @Before
  public void start() 
  {
    System.out.println("In @Before!");
    Interface1 mockInterface = mock(Interface1.class);
    when(helperclass.somefunction()).thenReturn(mockInterface);
  }

  @Test
  public void test()
  {
    System.out.println("In @Test!");
  }

  public static class Dummy {
    public final Interface1 interface1;
    public final HelperClass helperclass;

   @Inject
   Dummy(HelperClass helperclass) 
   {
     System.out.println("In dummy constructor!");
        this.interface1 = helperclass.somefunction();
        this.helperclass = helperclass;
   }
 }

  private static class HelperClass {
    Interface1 somefunction() {
      return new Interface1() {};
    }
  }

  private static interface Interface1 {

  }
}

Output:

In dummy constructor!
In @Before!
In @Test!

If you insist on doing it with @Mock and @InjectMocks, you could try using the answer argument instead:

@Mock(answer=Answers.RETURNS_MOCKS)

will make helperclass.somemethod() return a mock instead of null.


Honestly, it's not surprising that it works this way. The authors of Mockito really don't like Partial Mocks / Stubs, and explicitly say so in their documentation:

As usual you are going to read the partial mock warning: Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. How does partial mock fit into this paradigm? Well, it just doesn't... Partial mock usually means that the complexity has been moved to a different method on the same object. In most cases, this is not the way you want to design your application.

However, there are rare cases when partial mocks come handy: dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) However, I wouldn't use partial mocks for new, test-driven & well-designed code.

Having helperclass return something other than null is a partial mock, and therefore they won't like it.

Question:

How can I capture (for assertion purposes) the parmeters passed to a static stub method call?

The methodBeingStubbed looks like this...

public class SomeStaticClass{
protected static String methodBeingStubbed(Properties props){
...

I am stubbing the method call because it i need to verify that it gets called...

PowerMockito.stub(PowerMockito.method(SomeStaticClass.class, "methodBeingStubbed")).toReturn(null);
PowerMockito.verifyStatic();

But I now also want to know what properties were passed to this "methodBeingStubbed" and assert it is as expected


Answer:

After the call to verifyStatic, you'll need to actually call the method you're trying to verify, as in the documentation here:

PowerMockito.verifyStatic(Static.class);
Static.thirdStaticMethod(Mockito.anyInt());

At that point you can use Mockito argument captors, as demonstrated (but not tested):

ArgumentCaptor<Properties> propertiesCaptor =
    ArgumentCaptor.forClass(Properties.class);

PowerMockito.verifyStatic(SomeStaticClass.class);
SomeStaticClass.methodBeingStubbed(propertiesCaptor.capture());

Properties passedInValue = propertiesCaptor.getValue();

If you're used to @Mock annotations, or you need to capture a generic (as in List<String>), you may also be interested in using the @Captor annotation instead.

Question:

So I have the following interface:

public interface IFragmentOrchestrator {
    void replaceFragment(Fragment newFragment, AppAddress address);
}

How can I create a spy with mockito that allows me to hook ArgumentCaptor-objects to calls to replaceFragment()?

I tried

    IFragmentOrchestrator orchestrator = spy(mock(IFragmentOrchestrator.class));

But mockito complains with "Mockito can only mock visible & non-final classes."

The only solution I've come up with so far is to implement an actual mock of the interface before I create the spy. But that kind of defeats the purpose of a mocking framework:

public static class EmptyFragmentOrchestrator implements IFragmentOrchestrator {
    @Override
    public void replaceFragment(Fragment newFragment, AppAddress address) {

    }
}

public IFragmentOrchestrator getSpyObject() {
    return spy(new EmptyFragmentOrchestrator());
}

Am I missing something fundamental? I've been looking through the docs without finding anything (but I may be blind).


Answer:

Spying is when you want to overlay stubbing over an existing implementation. Here you have a bare interface, so it looks like you only need mock:

public class MyTest {
  @Captor private ArgumentCaptor<Fragment> fragmentCaptor;
  @Captor private ArgumentCaptor<AppAddress> addressCaptor;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testThing() {
    IFragmentOrchestrator orchestrator = mock(IFragmentOrchestrator.class);

    // Now call some code which should interact with orchestrator 
    // TODO

    verify(orchestrator).replaceFragment(fragmentCaptor.capture(), addressCaptor.capture());

    // Now look at the captors
    // TODO
  }
}

If, on the other hand, you really are trying to spy on an implementation, then you should do that:

IFragmentOrchestrator orchestrator = spy(new IFragmentOrchestratorImpl());

This will call the actual methods on IFragmentOrchestratorImpl, but still allow interception with verify.

Question:

I'd like to stub some code so that a vararg method returns true when one of the arguments matches a specific value. For example, given the existing code that I can't change:

(Using Kotlin here, but I figure this applies to any Java situation.)

class Foo {
    fun bar(vararg strings : String) : Boolean {
        // Iterates `strings` and returns true when one satisfies some criteria
    }
}

... I want to write stub code similar to this:

val foo = Foo()
whenever(foo.bar(eq("AAA"))).thenReturn(true)

This works fine when the call is exactly foo.bar("AAA").

However, there are times when the code under test makes the call foo.bar("AAA", "BBB"), and in those cases, it fails.

How can I revise my stub code so it works when any number of varargs are passed in the call?

Edit Flagged as a possible duplicate; in that case, the scenario contemplates the complete omission of the varargs in the call. Here, I'm trying to match one specific element of the varargs array.


Answer:

You have to stub your method 2 times. First the least specific stub:

val foo = Foo()
whenever(foo.bar(any())).thenReturn(false) // or whatever you want to return/throw here

And then the more specific single argument method:

whenever(foo.bar(eq("AAA"))).thenReturn(true)

After your comment you may aswell use something like this (using Java this time):

when(foo.bar(any())).thenAnswer(invocation -> {
    for (Object argument : invocation.getArguments()) {
        if ("AAA".equals(argument)) return true;
    }
    return false;
});

And the same in Kotlin

whenever(foo.bar(any()).thenAnswer {
    it.arguments.contains("AAA")
}

Question:

I have a test that expects an exception to be thrown when a user is found to be suspended.

  @Test(expected = SuspendedException.class)
  public void testGetUserKeychain_WhenOneUserSuspended_ShouldThrowSuspended() throws Throwable {
    when(userKeychain.getUserStatus()).thenReturn(UserState.OK);
    when(otherUserKeychain.getUserStatus()).thenReturn(UserState.SUSPENDED);
    when(keyLookup.lookupKeychainsByUserId(any()))
        .thenReturn(CompletableFuture.completedFuture(ImmutableMap.copyOf(multiUserKeychains)));
    try {
      padlockUtil.getKeychains(
          Sets.newSet("userid", "otheruserid")).toCompletableFuture().get();
    } catch (ExecutionException e) {
      throw e.getCause();
    }
  }

But the exception I get instead is:

org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected in test class: PadlockUtilTest
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at com.xyz.server.padlock.PadlockUtilTest.testGetUserKeychain_WhenOneUserSuspended_ShouldThrowSuspended(PadlockUtilTest.java:119)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

I believe this is because in PadlockUtil::getKeychains, the suspended user is encountered before the OK user, so Mockito is complaining that the OK user didn't need to be stubbed.

Because if I swap who's suspended and not...

when(userKeychain.getUserStatus()).thenReturn(UserState.SUSPENDED);
when(otherUserKeychain.getUserStatus()).thenReturn(UserState.OK);

...then Mockito is happy. As opposed to just switching "userid" and "otheruserid"; there Mockito is still unhappy, presumably because that's not where the order is determined later.

It may be true that in this specific example I've set up, it's not necessary to stub the first user. But that could be misleading in the future; I want the stub to exist, and it's not because of "lenience," IMO. I could also suspend the first user instead of the second, but it doesn't explicitly address this subtlety, and it could come up again later, confusing developers.

What is the proper way to do this so the underlying order of operations (we're dealing with Sets and Maps here, nothing else) is not a factor in the test?


Answer:

Lenient mocks are what you want, if you can't just use a real UserKeychain.

Mockito.lenient().when(userKeychain.getUserStatus()).thenReturn(UserState.OK);
Mockito.lenient().when(otherUserKeychain.getUserStatus()).thenReturn(UserState.SUSPENDED);

Mockito is designed to replace systems where you can't use the real system in your test, particularly in systems that predictably invoke services instead of getting properties from data objects (or other idempotent actions). Because your system doesn't call those methods in a deterministic order, and because the calls aren't expensive and don't have side effects, I would recommend just going with the "lenient" option.


Imagine this case instead, where you are testing deleting user 1001:

when(userRpc.deleteUser(1001)).thenReturn(RPC_SUCCESS);
when(userRpc.deleteUser(1002)).thenReturn(RPC_SUCCESS);  // unnecessary

The test might pass if you ever delete the wrong user: Over-stubbing has masked a problem. Compare with this:

when(userRpc.fetchExpensiveUserDetails(1001)).thenReturn(user1001);
when(userRpc.fetchExpensiveUserDetails(1002)).thenReturn(user1002);  // unnecessary

Depending on what you're testing, this might be dangerous, but might not be so bad. Simulating a slow mobile network or with expensive data, maybe it is entirely against spec for you to fetch too much. However, in other cases, it may be acceptable. Finally, compare this case:

when(calculationResult.getRealComponent()).thenReturn(-1d);
when(calculationResult.getComplexComponent()).thenReturn(5);
when(calculationResult.getShortString()).thenReturn("-1 + 5i");

calculationResult looks an awful lot like a data object, and it is probably not a critical part of your test which of your methods to call or whether you're calling all of them. This is a case where Mockito's strict stubbing hinders you rather than helping you, and might be a case where you want to make some of those stubbings lenient. You might also choose to make the entire mock lenient, which particularly makes sense if you were to create a test helper method like stubCalculationResult(-1, 5) that prepared an entire object for you like that.

The only option better than that is to use a real object. In my example, if CalculationResult is an existing well-defined object, it may be lower risk overall to use a real one than to mock the behavior you believe at test-writing time to be correct. Similarly for your case, if you have access to a UserKeychain constructor that populates UserStatus etc, then it may be safer to use that in a test.

Though this might appear at first glance to be a slippery slope into turning a unit test into an integration test, I'd like to clarify that I'm recommending this only for data objects, which have no dependencies, and which ideally are immutable objects that have no methods with side-effects. If you use dependency injection, these are the type of single-implementation data holders that you would call new on rather than getting from your graph. This is also a good reason to separate your data objects so they are immutable and easy to construct, and to shift your services to consume those objects rather than giving methods to the data objects (favoring loginService.login(user) rather than user.login(loginService)).

Question:

I am using some library that throws an exception and would like to test that my code behaves correctly when the exception is thrown. Stubbing one of the overloaded methods does not seem to work. I am getting this error: Stubber cannot be applied to void. No instance types of variable type T exists so that void confirms to T

`public class AnotherThing {
  private final Something something;

  public AnotherThing(Something something) {
    this.something = something;
  }

  public void doSomething (String s) {
    something.send(s);
  }
}

public class Something {

  void send(String s) throws IOException{

  }

  void send(int i) throws IOException{

  }
}

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class OverloadedTest {

  @Test(expected = IllegalStateException.class)
  public void testDoSomething() throws Exception {
    final Something mock = mock(Something.class);
    final AnotherThing anotherThing = new AnotherThing(mock);

    doThrow(new IllegalStateException("failed")).when(anotherThing.doSomething(anyString()));
  }
}`

Answer:

You've misplaced the close parenthesis. When using doVerb().when() syntax, the call to when should only contain the object, which gives Mockito a chance to deactivate stubbed expectations and also prevents Java from thinking you're trying to pass a void value anywhere.

doThrow(new IllegalStateException("failed"))
    .when(anotherThing.doSomething(anyString()));
//                    ^ BAD: Method call inside doVerb().when()

doThrow(new IllegalStateException("failed"))
    .when(anotherThing).doSomething(anyString());
//                    ^ GOOD: Method call after doVerb().when()

Note that this is different from when calls when not using doVerb:

//               v GOOD: Method call inside when().thenVerb()
when(anotherThing.doSomethingElse(anyString()))
    .thenThrow(new IllegalStateException("failed"));

Question:

Here's my stubbed method:

 Mockito.when(restTemplateMock.postForEntity(anyString(), any(), eq(String.class))).thenReturn(new ResponseEntity<String>(HttpStatus.OK));

How can I grab hold of the argument sent to this method? The above postForEntity method has 3 arguments.


Answer:

final ArgumentCaptor<String> arg1Captor = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<Object> arg2Captor = ArgumentCaptor.forClass(Object.class);
final ArgumentCaptor<Class<?>> arg3Captor = ArgumentCaptor.forClass(Class.class);

Mockito.verify(restTemplateMock).postForEntity(arg1Captor, arg2Captor, arg3Captor);

Assert.assertEquals("Whatever", arg1Captor.getValue());