Mockito Strict Stubbing and The UnnecessaryStubbingException

1. Overview

In this quick tutorial, we’ll learn about the Mockito UnnecessaryStubbingException. This exception is one of the common exceptions we’ll likely encounter when using stubs incorrectly.

We’ll start by explaining the philosophy behind strict stubbing and why Mockito encourages its use by default. Next, we’ll take a look at exactly what this exception means and under what circumstances it can occur. To conclude, we’ll see an example of how we can suppress this exception in our tests.

To learn more about testing with Mockito, check out our comprehensive Mockito series.

2. Strict Stubbing

With version 1.x of Mockito, it was possible to configure and interact with mocks with no kind of restriction. This meant that, over time, tests would often become overcomplicated and at times harder to debug.

Since version 2.+, Mockito has been introducing new features that nudge the framework towards “strictness”. The main goals behind this are:

  • Detect unused stubs in the test code

  • Reduce test code duplication and unnecessary test code

  • Promote cleaner tests by removing ‘dead’ code

  • Help improve debuggability and productivity

Following these principles helps us create cleaner tests by eliminating unnecessary test code. They also help avoid copy-paste errors as well as other developer oversights.

To summarise, strict stubbing reports unnecessary stubs, detects stubbing argument mismatch and makes our tests more DRY (Don’t Repeat Yourself). This facilitates a clean and maintainable codebase.

2.1. Configuring Strict Stubs

Since Mockito 2.+, strict stubbing is used by default when initializing our mocks using either of:

  • MockitoJUnitRunner

  • MockitoJUnit.rule()

Mockito strongly recommends the use of either of the above. However, there is also another way to enable strict stubbing in our tests when we’re not leveraging the Mockito rule or runner:

Mockito.mockitoSession()
  .initMocks(this)
  .strictness(Strictness.STRICT_STUBS)
  .startMocking();

One last important point to make is that in Mockito 3.0, all stubbings will be “strict” and validated by default.

3. UnnecessaryStubbingException Example

Simply put, an unnecessary stub is a stubbed method call that was never realized during test execution.

Let’s take a look at a simple example:

@Test
public void givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException() {
    when(mockList.add("one")).thenReturn(true); // this won't get called
    when(mockList.get(anyInt())).thenReturn("hello");
    assertEquals("List should contain hello", "hello", mockList.get(1));
}

When we run this unit test, Mockito will detect the unused stub and throw an UnnecessaryStubbingException:

org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at com.baeldung.mockito.misusing.MockitoUnecessaryStubUnitTest.givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException(MockitoUnecessaryStubUnitTest.java:37)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

Thankfully, it’s quite clear from the error message what the problem is here. We can also see that the exception message even points us to the exact line which causes the error.

Why does this happen? Well, the first when invocation configures our mock to return true when we call the add method with the argument “one”. However, we do not then invoke this method during the rest of the unit test execution.

Mockito is telling us that our first when line is redundant and perhaps we made an error when configuring our stubs.

Although this example is trivial, it’s easy to imagine when mocking a complex hierarchy of objects how this kind of message can assist debugging and be otherwise very helpful.

4. Bypassing Strict Stubbing

Finally, let’s see how to bypass strict stubs. This is also known as lenient stubbing.

Sometimes we need to configure specific stubbing to be lenient while maintaining all the other stubbings and mocks to use strict stubbing:

@Test
public void givenLenientdStub_whenInvokingGetThenThrowUnnecessaryStubbingException() {
    lenient().when(mockList.add("one")).thenReturn(true);
    when(mockList.get(anyInt())).thenReturn("hello");
    assertEquals("List should contain hello", "hello", mockList.get(1));
}

In the above example, we use the static method Mockito.lenient() to enable the lenient stubbing on the add method of our mock list.

Lenient stubs bypass “strict stubbing” validation rules. For example, when stubbing is declared as lenient, it won’t be checked for potential stubbing problems such as the unnecessary stubbing described earlier.

5. Conclusion

In this brief article, we began by introducing the concept of strict stubbing in Mockito and understood the philosophy behind why it was introduced and why it’s important.

Next, we looked at an example of the UnnecessaryStubbingException before finishing with an example of how to enable lenient stubbing in our tests.

As always, the full source code of the article is available over on GitHub.

Leave a Reply

Your email address will not be published.