Effective Mockito Part 5
With this effective Mockito Post I want to share a really simple pattern with you. We call this pattern “check answers” and we use it whenever we work with Mockito Answers. The code resulting from creating Mockito Answers generally looks ugly. But, as good programmers we care about test quality, right? :)
Let’s see how we can make better looking answers using the “check answer” pattern. Mockito’s Answers are great when you need to verify that a method was called with specific parameters, or you need to execute an operation that also needs to be mocked. I’m sure you have seen situations where Answers were very useful. Let’s dive into a simple example. Our fancy program consists of three classes which are listed in the snippet below.
public class MyRuntimeState {
private boolean state;
public void setState( boolean state ) {
this.state = state;
}
public boolean isTrue() {
return state;
}
}
public class MyDelegate {
public void doSomething( MyRuntimeState state ) {
// do some fancy operation
}
}
public class MyObject {
private final MyDelegate delegate;
public MyObject( MyDelegate delegate ) {
this.delegate = delegate;
}
public void operate() {
MyRuntimeState state = new MyRuntimeState();
state.setState( true ); // this is the important fact we want to test
delegate.doSomething( state );
}
}
As you can see we have the Types MyObject
, MyDelegate
and MyRuntimeState
. MyObject
needs a MyDelegate
in its constructor. In the operate method, MyObject
calls MyDelegate
’s doSomething
method with a newly created MyRuntimeState
object. Let’s assume that for some reason our fake system needs a MyRuntimeState
with the state ‘true
’ to work (be creative - it’s just an example ;)). So, MyObject
needs to set the state of the MyRuntimeState
object to true. This is exactly the case where Answers are useful to verify that the state is true within the doSomething
invocation (we can probably also do this with verify in this example, but there are harder operations out there where verify can’t be used). Let’s look at the test for this mechanism.
@RunWith( MockitoJUnitRunner.class )
public class MyObjectTest {
@Mock
private MyDelegate delegate;
private MyObject myObject;
@Before
public void setup() {
myObject = new MyObject( delegate );
}
@Test
public void testSendsRightState() {
doAnswer( new Answer() {
@Override
public Object answer( InvocationOnMock invocation ) throws Throwable {
MyRuntimeState state = ( MyRuntimeState )invocation.getArguments()[ 0 ];
assertTrue( state.isTrue() );
return null;
}
} ).when( delegate ).doSomething( any( MyRuntimeState.class ) );
myObject.operate();
}
}
You see that it's a fully working test that tests exactly what we want, but it's also a smell. I dislike several things in the testSendsRightState method. The first thing is the method chaining over several lines. The second thing is that we have an indentation level of three which leads to unreadable code. The third thing is that we can't see at a glance what will be tested. The fourth thing I don't like is that the assert statement comes before the actual operate call at least in the writing of the code. The last thing is that this method is way too long.
Let's try to get rid of most of the smells by simply doing one refactoring. You may say that this is obvious, and yes it is;). We need to extract the creation of the Answer object into a separate method. I name these methods createCheck***Answer (*** stands for a named check) because the answers that will be created are invoking the actual asserts. The result can look like this:
@Test
public void testSendsRightState() {
Answer checkStateAnswer = createCheckStateAnswer();
doAnswer( checkStateAnswer ).when( delegate ).doSomething( any( MyRuntimeState.class ) );
myObject.operate();
}
private Answer createCheckStateAnswer() {
return new Answer() {
@Override
public Object answer( InvocationOnMock invocation ) throws Throwable {
MyRuntimeState state = ( MyRuntimeState )invocation.getArguments()[ 0 ];
assertTrue( state.isTrue() );
return null;
}
};
}
This simple refactoring has a huge impact on our test method. The test method has only a length of three lines of code now. The indentation level is one. The call chain fits into one line. Even the createCheckStateAnswer is more readable because it's not surrounded by chained calls. One drawback still resists this solution. That is, that the assert is now called within another method. To me, this is a very low price to pay compared to the problems in the first test. And, the best thing about this solution is that when you only read the test method you see at first glance that an answer called checkStateAnswer was created that obviously does something like check a state. Other programmers should be able to understand most of the test method without reading the createCheckStateAnswer method.
I know that this solution is very simple and for you, may be obvious. But when I started with Answers I didn't do this for reasons only the Programming Gods know now. If you have any other things related to Answers in your repertoire please share them with us in a comment.
Read the other Effective Mockito posts:
Effective Mockito Part 1
Effective Mockito Part 2
Effective Mockito Part 3
Effective Mockito Part 4