Avoid annotations with Mockito

On the Mockito mailing list and on Stackoverflow, there are a significant number of questions that actually reveal that the person asking did not perfectly understand what the Mockito annotations do. Indeed, the annotations are rather magical and their behavior is definitely not obvious.

Since they are mostly syntactic sugar (although whether they actually improve readability is debatable), my recommendation is to do without them entirely. Here are a few examples.

Here, the issue is that @Mock is read by Brice Dutheil’s MockitoJUnitRunner only after the test class is instantiated, that is, after the ClassUnderTest is instantiated. So ClassUnderTest only received a null value, not the mocked dependency.

This one is more tricky. Although it will work in simple cases, it tends to behave strangely in more complex classes, as pointed out by in a recent thread on the Mockito mailing list: “since 1.9.5, mocks created by Mockito.mock() will be included in the list of injection candidate; that does explain that the mock of ClassToInjected is injected in itself somewhere in an upper class.”
We should also note that it discourages making dependencies final, which is not a good thing.

Yes, there are some redundancies (in the names of the dependency class), but I believe this much is acceptable in a test.

Other available annotations include @Spy and @Captor, which behave in ways similar to @Mock. However, since spies and captors should be used sparingly, to say the least, there are few cases when it makes sense to declare them in the attributes section. Intentions are a lot clearer when spies and argument captors are instantiated within methods anyway.

In summary, the benefits provided by the annotations provided by Mockito do not seem to justify the reduction in readability. I recommend avoiding them.

I’d argue that the very fact that this is not blindingly obvious is an argument in favour of avoiding annotations… and make dependencies obvious by changing the code under test to allow for injection in a normal, manual way. This approach is also very much in the spirit of Mockito: its goal is not really to work with existing code, but rather to guide the creation of new code. Other tools are better at working with existing code bases.

Ok, so it’s 6 years later, but I wanted to add a thought. I try to avoid instantiating member variables when they are declared as a member of the test class. In other words, I try to avoid this:

private ClassUnderTest instance = new ClassUnderTest();

The reason? It doesn’t give you a nice clean new object for each test. So your tests are not stateless / completely independent of each other. In the vast majority of cases, this is fine and not a problem – but the potential is there. Instantiating them in a @BeforeEach setup method ensures you get a shiny new object for each test with no residual state from another method. It would also resolve the problem that you mentioned of having the mock instantiated after new ClassUnderTest() is called. I don’t need to be afraid of @Mock.

I would argue that @Mock makes your intentions very clear and is much more readable. I’m not sure how this is debatable. It may not reduce your code line count, but @Mock & @InjectMocks make it very clear which variables are mocked dependencies and which is the CUT. That said, there are times when Mockito.mock() is better, and I think we should just use good judgment when those times are.