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.