Mockito's performance cost
In the Java world, Mockito is very well known for its ability to mock external dependencies or side effects in one’s unit tests suite.
However, I’ve seen it used for things that shouldn’t need mocking. I’ve almost always seen a performance hit.
This post quantifies that performance hit, and gives another reason why abusing Mockito is not a good idea.
1. Context
I’ve seen Mockito abused to mock beans, or plain objects getters.
Let’s make a dummy one:
public class Data {
private final String name;
public Data(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
In real cases, the class being mocked might have many more properties (already a sign of sketchy design IMO).
Now that we have a Data
, let’s make a Functionality
using it:
public class Functionality {
public static String compute(final Data data) {
return data.getName();
}
}
2. Tests with mocks
In this case, Data
is never explicitly instantiated, and its getName
is
mocked with the value we want to pass.
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.doReturn;
@ExtendWith(MockitoExtension.class)
public class FunctionalityMockTest {
@Mock
private Data data;
@Test
void testMe0() {
final var name = "hello0";
doReturn(name).when(data).getName();
var output = Functionality.compute(data);
Assertions.assertEquals(name, output);
}
// same test duplicated 20 times, with "hello0" to "hello19"
}
3. Tests without mocks
Same tests, but now we need to explicitly instantiate Data
.
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class FunctionalityNoMockTest {
@Test
void testMe0() {
final var name = "hello0";
final var data = new Data(name);
var output = Functionality.compute(data);
Assertions.assertEquals(name, output);
}
// same test duplicated 20 times, with "hello0" to "hello19"
}
4. Performance
Each test file contains 20 tests doing the same thing with a slightly different string.
After running each 20 tests 10 times in a row, here are the results:
Case | Average time (ms) |
---|---|
Mocks |
246±6 |
No Mocks |
1±1 |
5. Conclusion
In this case, using mocks is ≈240 times slower than not using mocks.
Unit tests should be fast (≈100 tests per second), and using mocks should only really be used at the edge for side effects, and should always be avoided otherwise.