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.
The answer approach is also very useful when you just want a method to return one of the arguments (using invocation.getArguments()).
I can’t rework the example. Where is the variable “theString” defined?
great! thenAnswer allowed to delay evaluation of result, thanks for sharing this info. thanks a lot!
I think in the sample I used a member.
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());
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. 🙂
[…] if captured method calls can do it.For example, a Mockito example is described in this blog entry:http://www.planetgeek.ch/2010/07…Where the "Answer" mechanism is used. To capture the state in an "answer" […]
I am trying to use this doAnswer thing and I can’t for the life of me figure out why netbeans complains that it does not know what Answer is. Which package should I include for this to work?