question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

MocktioExtension being too strict with stubs in `@BeforeEach` method

See original GitHub issue

I’ve written a test case for a class which persists errors to a file and thus I have a handful of tests to prove that non-errors cases are not persisted to a file however the majority of the tests in the test case are related to triggering various error scenarios.

As the majority of test cases (~70%) require mock to supply the persistence file I’ve included a stub for that in the setup method (annotated using junit5 @BeforeEach). I’m running the tests using MockitoExtension which fails tests with org.mockito.exceptions.misusing.UnnecessaryStubbingException for the 30% of test which demonstrate that the file isn’t use when messaging works.

While it is true that the stub is unused in those test I think it is discouraging readability by duplicating the stubbing to the majority of the tests in the class. From the UnnecessaryStubbingException Javadoc

Mockito JUnit Runner triggers UnnecessaryStubbingException only when none of the test methods use the stubbings. This means that it is ok to put default stubbing in a ‘setup’ method or in test class constructor. That default stubbing needs to be used at least once by one of the test methods.

I expected the Extension to offer the same behaviour.

I’ve contrived a simple example below which fails.

I think this is related to: https://github.com/mockito/mockito/issues/769 but I think it is more of an issues with the MockitoExtension than strictness it self.

Dependencies on java 8 (8.0.171-oracle):

<dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency><dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.23.4</version>
        <scope>test</scope>
    </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>2.23.4</version>
            <scope>test</scope>
        </dependency>
package nz.samandems.mockito;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class MockitoLenienceyTestCase {

    @Mock
    private Dependency dependency;

    private SystemUnderTest systemUnderTest;


    @BeforeEach
    void setUp() {
        Mockito.when(dependency.doWork()).thenReturn(true);
        systemUnderTest = new SystemUnderTest(dependency);
    }


    @Test
    void shouldDoWork() {
        //Given

        //When
        systemUnderTest.doThing(true);

        //Then
        Mockito.verify(dependency).doWork();
    }

    @Test
    void shouldDoNoWork() {
        //Given

        //When
        systemUnderTest.doThing(false);

        //Then
        Mockito.verifyZeroInteractions(dependency);
    }


    private class SystemUnderTest {

        private final Dependency dependency;


        private SystemUnderTest(final Dependency dependency) {
            this.dependency = dependency;
        }


        public boolean doThing(boolean works) {
            if (works) {
                return dependency.doWork();
            }
            else {
                return false;
            }
        }
    }

    private interface Dependency {

        boolean doWork();
    }
}

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:12
  • Comments:18 (6 by maintainers)

github_iconTop GitHub Comments

6reactions
mockitoguycommented, Nov 24, 2019

@Mock(lenient = true) on a field

alternative:

@BeforeEach
public void setup() {
   lenient().when(mock.foo()).thenReturn(true);
}

This way, only the specific stubbing is “lenient”.

1reaction
TehBakkercommented, Sep 30, 2020

Any news on this ? Same probleme 90% of my tests need a when call and the other 10% throw exception.

I do not want to do lenient though as i feel UnnecessaryStubbingException is good just need to check with the whole tests

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mockito Strict Stubbing and The UnnecessaryStubbingException
Simply put, an unnecessary stub is a stubbed method call that was never realized during test execution. Let's take a look at a...
Read more >
How to resolve Unneccessary Stubbing exception
Unnecessary stubs are stubbed method calls that were never realized during test execution (see also MockitoHint), example:
Read more >
Unit tests with Mockito - Tutorial - Vogella.com
The strict stubs rule helps you to keep your test code clean and checks for common oversights. It adds the following: test fails...
Read more >
Creating Deep Stubs With Mockito to Chain Method Stubbing
A Possible Solution: Mockito Deep Stubs · @ExtendWith(MockitoExtension.class) · class DeepStubClientTest · @Mock(answer = Answers.RETURNS_DEEP_STUBS).
Read more >
Testing Your Application - Quarkus
package org.acme.getting.started.testing; import io.quarkus.test.junit. ... If you use this method in a @BeforeAll method the mock will take effect for all ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found