Question: How to use STRICT_STUBS together with Mockito.mock()

926 views
Skip to first unread message

Svyatoslav Chatchenko

unread,
Jan 2, 2019, 9:08:40 AM1/2/19
to mockito
I'm using Mockito.mock() in my tests (via mockito-kotlin) and I'd like to enable STRICT_STUBS. To following code works:

class ExampleTest {
    @get:Rule val rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS)
    lateinit var mockedFoo: Foo
    lateinit var booUnderTest: Bar

    @Before
    fun setUp() {
        mockedFoo =  Mockito.mock(Foo::class.java)
        booUnderTest =  Bar(mockedFoo)
    }

    @Test
    fun shouldFailWithStubbingProblem() {
        `when`(mockedFoo.doFoo(5)).thenReturn("five")
        `when`(mockedFoo.doFoo(3)).thenReturn("three")
        assertThat(booUnderTest.doBar(5)).isEqualTo("five times")
    }
}

I receive 

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'doFoo' method:
    foo.doFoo(3);
    -> at ExampleTest2.shouldCallFoo(ExperimentsTest.kt:63)
 - has following stubbing(s) with different arguments:
    1. foo.doFoo(5);
      -> at ExampleTest2.shouldCallFoo(ExperimentsTest.kt:62)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
    Please use 'will().given()' or 'doReturn().when()' API for stubbing.
  - stubbed method is intentionally invoked with different arguments by code under test
    Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.

But when I create mock during field initialisation, test passes without any message from Mockito.

class ExampleTest {
    @get:Rule val rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS)
    val mockedFoo: Foo = Mockito.mock(Foo::class.java)
    val booUnderTest: Bar = Bar(mockedFoo)

    @Test
    fun shouldFailWithStubbingProblem() {
        `when`(mockedFoo.doFoo(5)).thenReturn("five")
        `when`(mockedFoo.doFoo(3)).thenReturn("three")
        assertThat(booUnderTest.doBar(5)).isEqualTo("five times")
    }
}

I assume, that's because field initialisation happens before Rule is executed. 

Question: is that possible to use Mockit.mock during field initialisation, but enable strict mocks?
Reply all
Reply to author
Forward
0 new messages