Beware the Mockito Unit Test Crutch

2022-06-07 tech coding java unit-testing mockito

Mockito is a great and standard tool for Java unit testing, but it can easily be overused to the point where it masks deeper problems in your code.

Mockito’s @Spy and @Mock annotations (or their Mockito.spy() and Mockito.mock() equivalents) are of course great for customizing behavior of class dependencies to setup the conditions needed by your code in a unit test. But on the minus side, too often I see poorly modularized code written without testability in mind, and then a giant spaghetti pile of Mockito code to delicately test it all. Such tests are hard to understand, hard to maintain, and worst of all, sometimes so mocked-up and tautological that they effectively test nothing.

I encourage people to look beyond Mockito band-aids and think more deeply about how they can write more modular, testable code in the first place. Such code will be more robust, easier to understand, and so easy to comprehensively test that there will be no place left for bugs to hide.

Let’s see some examples

Hard to Test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Wizard {
	
	public static final String WEEKDAY_MSG = "more work lies in your future";
	public static final String WEEKEND_MSG = "calm and relaxation lie just ahead";
	
	static Random rand = new Random();
	
	Spell abracadabra = new SpellAbracadabra();
	Spell hocuspocus = new SpellHocusPocus();
	
	int abraCount, hocusCount;
	
	interface Spell {
		public abstract String chant();
	}
	
	static class SpellAbracadabra implements Spell {
		@Override
		public String chant() {
			return "abracadabra";
		}
		
	}

	static class SpellHocusPocus implements Spell {
		@Override
		public String chant() {
			return "hocus pocus";
		}
		
	}

}

Easy to Test

If you find yourself thinking, “How am I ever going to write the unit test for this?”, take a step back and realize that rather than struggling to write a unit test for difficult code, you can improve the code itself, after which unit testing becomes a breeze.