Recently I’ve spent a fair bit of time moving some older unit tests from JUnit3 with JMock1 to JUnit4 with Mockito. It’s been a real pleasure to see how much more clearly the tests read afterwards and while the benefits would not have been so marked if I’d been moving the test from Easymock, I’m clear there would have been a noticable improvement.
Mockito has many helpful little touches. The @Mock annotation not only reduces boilerplate, but also clearly identifies mocks in member variable definitions. The well thought out stack traces present failure information as clearly as possible. However, where it really stands out from other mocking frameworks is that it makes you think more clearly about what it is you’re actually testing and then express that intent in the test.
Defining the behaviour of mocks and verifying that expected interactions with them have occurred are two distinct activities within a test, but other mocking frameworks have confused the two.
As I’ve been switching the tests over, it’s become abundantly clear that the authors of the tests have often implicitly introduced a check that a particular function was called, even though it’s not directly relevant to the test, because JMock makes it easier to do so than not. This leads to unnecessarily brittle tests, coupled tightly to the class under test’s implementation.
Equally I’ve sometimes almost missed verifications of calls which are critical to the intent of the test because scanning the test they look almost identical to those which merely set up default behaviour for mocks. In JMock and Easymock they appear, like those, before the call to the method actually being called, rather than with your other assertions after the method has executed. By allowing verification it’s own distinct, post-execution syntax, Mockito highlights immediately the importance and distinct nature of verifications.
This does inevitably mean that occasionally you need two calls with Mockito, one to set expectations on the mock and one to verify that interactions occured, where with other mocking frameworks one would suffice. This is in no way a bad thing. It’s not just that in such cases you are performing two distinct operations. The rare cases where it is necessary generally point out that the mocked method is trying to do two distinct jobs. It’s another step in using tests to help identify flaws in design.
Mockito makes simple state-based testing with stubbed-out mocks easy and makes you notice when you’re taking the drastic step of tying one classes tests to the details of it’s interaction with another.