Yesterday I send out a tweet in which I claimed that Mockito and clean tests seem not to go hand in hand. It triggered some reactions on which I’ll elaborate in this post a bit more than in the Twitter conversations.
First of all, in no way I intend to say that your tests are a mess by definition if you use Mockito. I am saying that Mockito doesn’t really help keeping your tests clean. Rather it puts that burden on you.
The responses were from @sdudzin and @jeroenrosenberg, for which I like to thank them. Their reactions included that it’s kind of a bold statement, what is my definition of clean tests, why Mockito breaks that, Mockito provides feedback about design, and that verifying that an invocation did not happen is over specification.
So, yes, my tweet was a bit of a bold statement. It even might be exaggerated a bit. But that doesn’t invalidate it - it is my opinion on Mockito.
The context in which I tweeted this is that I was implementing a dispatch function. Based on some input, a single method must be invoked on a collaborator. As I TDD-ed my way in soon I refactored to a switch statement. I’m not sure why but in one of the branches I forgot to break. The result is a bug - which luckily I caught while writing the next test.
In an after-method I added a call to
verifyNoMoreInteractions causing these types of bugs to show up for any test, polluting the
tearDown method with this incoherent statement.
Which brings me to my definition of clean tests. In my perception, a clean test simply stated is a test that clearly communicates its intent. It’s name clearly states what is tested, and the implementation clearly describes how it’s tested.
In my opinion adding these statements adds noise to the tests. These statements are incoherent with the tests and are only necessary to work around strange behavior of a test library. Because of this you have to work hard to keep your tests clean.
I don’t really agree on the statement that Mockito gives you feedback on the design. Test libraries don’t provide feedback. Tests do that. Test libraries only provide some convenience. Therefore I like test libraries to be as simple as possible, so the focus always lies on the test itself. Messy tests often tell you the design is messy. However, if a test library makes your tests just a little messier, it takes away this focus making it easier to ignore this feedback.
Obviously I do agree that having many mocks in one test indicates a design problem. In fact, if you need more than one mock in a test, you probably need to refactor. Also I completely agree that verifying for an interaction not to take place is over specification and should not be necessary. This actually leads to fragile tests.
That still leaves the fact that I don’t want my test doubles to ignore calls that didn’t specify myself. As Mockito’s ignorance cannot be switched off, the verification for no other interactions sadly is necessary. It’s exactly this kind of behavior that I don’t like about Mockito. Other examples include that I find setting up doubles with Mockito gets complicated much earlier than with a library like JMock.
This article is no way meant as a rant against Mockito. If you happen to like Mockito, that’s okay. If you don’t know about other libraries, it might be time to investigate some. Personally, at this moment I prefer JMock for test doubles in Java. I find JMock to enable me to clearly express the role of collaborators, while Mockito just makes it possible to setup test doubles. JMock also is much more consistent with other libraries, like RSpec, Jasmine and Sinon.
To wrap up I send my thanks to Siarhei and Jeroen for the conversations we had.