Mockito – Answer vs. Return

Did you had the problem your mock must act like a bean? And you could not create the object with the real implementation? And the interface was too large, so you would not create a innerclass for the test? I had this problem too. I solved it with the answer in mockito.

First of all we need an interface. On the interface we define a setter and a getter. Imagine we must be able to get back the value we set.  The sample interface will be quite easy but with a little imagination we know the interface would have a lot more methods. And we don’t want to implement the class in our test.

The interface would look like this:

public interface SetGet {
    void setString(String newString);
    String getString();
}

We create the mock as usual:

SetGetSample mock = Mockito.mock(SetGetSample.class);

Following code snipped shows how to record the value which is set on setString.

doAnswer(new Answer<Object>() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        theString = (String) invocation.getArguments()[0];
        return null;
    }
}).when(mock).setString(anyString());

We need the Answer for recording the input and do not give something back. Because there is a void return value we have to do the answer with the command doAnswer since the when only can be used on methods which have a return value.

We know there is a string used as parameter so we can cast the first argument to String. In other cases we should check if it is an instance of this type. And we set our field to the given value. (Yep, you read correct we need a field in the test class to set the value.

Now the code to get the recorded value:

when(mock.getString()).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
        return theString;
    }
});

You see, know we use the standard when but we use the thenAnswer instead of the thenReturn the difference is: answer will everytime be executed. Return remembers the value we told them in the when. And the following test will become a green bar. 🙂

mock.setString("foo");
assertEquals("foo", mock.getString());

mock.setString("bar");
assertEquals("bar", mock.getString());

I think this is not the solution you should use for a large interface. But imho this is a practicable solution if there is just a set of one or two setter/getter.

About the author

Adrian Elsener

8 comments

Recent Posts