Search code examples
javaunit-testingjunitmockitojunit-jupiter

Mockito throws UnnecessaryStubbingException for stub defined in generic @BeforeEach setup method


I have a unit test class where my unit under test is dependent on another class. The dependency is mocked using Mockito and then setup with a generic stub that's run before every unit test, using JUnit's @BeforeEach annotation. See the below pseudo-code.

@ExtendWith(MockitoExtension.class)
public class FooFactoryTest {

    @Mock
    private BarDependency barDependency;

    @InjectMocks
    private FooFactory unitUnderTest;

    @BeforeEach
    public void setup() {
        when(barDependency.leftBar(any())).thenReturn(new Bar());
        when(barDependency.rightBar(any())).thenReturn(new Bar());
    }

   ... many tests ...

This setup works perfectly for 9 of my 10 unit tests. Unfortunately one of my tests is failing with the following error:

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 nl.devillers.mockito.FooFactoryTest.setup(FooFactoryTest.java:69)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

Now, I understand the error and why it's thrown, because in that specific test my unit under test short-circuits early and doesn't hit all the stubs that have been setup. I'm aware there's a lenient option in Mockito, but that'll disable the check for the entire class/project.

My question is: how do I disable this strictness for one specific unit test?

Again: I do not want to disable the strictness at the class or project level, since I think it's valuable check. I also do not want to move my setup code to the tests that do need the stubs, because then I have to duplicate the setup code nine times. In this case I just want to disable or skip the check for this specific test.


Solution

  • You can avoid this check at the test-level by resetting the mock with the stub that's not being called. This is a bit of a work around, but it'll allow you to pass your test without having to make the mock lenient for your entire test class or removing the mock entirely from your setup method.

    To reset your barDependency mock, add the following line of code to the end of your test that is failing with a UnnecessaryStubbingException.

    Mockito.reset(barDependency);
    

    If none of the stubs on barDependency are being used, you can also place this line at the beginning of your test with your other arrangements, which is a little cleaner. Or alternately, put it at the top of your test method and then setup the stubs you do need. This essentially overrides whatever is being setup in your generic setup method.