More Thoughts about Mocking and State

Steve rightfully asked for the source of the
bad feelings we had about about adding a sequential return value feature to Mockito.
The issue is that a Mockito stub is stateless, i.e. the value returned depended solely on the
parameters being passed in when calling the stub.

Statelessness is generally a nice property. It makes a
test case a lot harder to understand, if you have to worry about the state of a mock. On the other hand there is a lot to
be gained from using state (at the end of the request, state is all that’s left). Some people argued
for some kind of general state machine implementation
in the mocking framework. I think this is utterly wrong. If you
are writing java code you should you use java to express general state machines, because that is what you choose.
The mocking library is only supposed to mock out simple interactions (i.e. to make the common case fast). Interestingly it thereby has
also some influence on the way you design your code. To phrase it differently: Most interactions should be simple.

Now back to the state. Having a feature that allows you to return a sequence of values, essentially makes your
mock a set of parallel linear automata (for those who are into statecharts), which is not very hard to understand, so
seems ok.
One of the dangers is that people stub out methods with interdependencies. Let’s consider an iterator. What you micht see
in the stubbing code is as follows:

stub(iterator.next())
            .toReturn("a")
            .toReturn("b");
 
stub(iterator.hasNext())
            .toReturn(true)
            .toReturn(true)
            .toReturn(false);

This code is of course treacherous, because it probably works in the first place, but it depends heavily on the class under
test calling the hasNext method exactly once each time before reading the next value. Now this is of course a bit of an
internal detail and using this code would lead to a brittle test, that has a high
impelentation specification smell. So one could argue that a more general soution
is needed. In my opinion that’s utterly wrong. Instead one should aim to use the general purpose interfaces
given by the java class library, such as iterator, streams, readers, collections. You can easily get an iterator for
testing purposes by creating a collection with some fixture objects and call iterator() on it.


Posted

in

by

Tags:

Comments

One response to “More Thoughts about Mocking and State”

  1. Johannes Link Avatar

    So how would you test a user of an iterator with the current version of Mockito, ie without state-based return values?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.