Home > Java, Test Driven Development, Testing > Mockito – Answer vs. Return

Mockito – Answer vs. Return

July 20th, 2010
Adrian Elsener

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.

 

Java, Test Driven Development, Testing , , , , , ,

  1. October 20th, 2010 at 11:59 | #1

    The answer approach is also very useful when you just want a method to return one of the arguments (using invocation.getArguments()).

  2. ichbindrin
    February 7th, 2011 at 17:55 | #2

    I can’t rework the example. Where is the variable “theString” defined?

  3. February 8th, 2011 at 19:42 | #3

    great! thenAnswer allowed to delay evaluation of result, thanks for sharing this info. thanks a lot!

  4. Adrian Elsener
    February 14th, 2011 at 07:28 | #4

    I think in the sample I used a member.

  5. February 26th, 2011 at 11:52 | #5

    Why don’t just

    doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
    when(mock.getErrorMessage()).thenReturn((String) invocationOnMock.getArguments()[0]);
    return null;
    }
    }).when(mock).setErrorMessage(anyString());

  6. Adrian Elsener
    March 6th, 2011 at 21:41 | #6

    I think this works too.
    I preferred the do answer and when sample to illustrate both sides of a call.
    But your version is quite simple. :)

  1. June 24th, 2011 at 02:15 | #1