Correct usage of strict stubbings -> PotentialStubbingProblem: Strict stubbing argument mismatch
See original GitHub issueHi guys,
This is following is almost a copy paste from the mockito google group/forum, which I was recommended to do: https://groups.google.com/forum/#!topic/mockito/WDKfavtJkCg
Relevant Versions:
OS : Fedora Linux 4.18.14-200.fc28.x86_64
mockito : 2.23.0
junit : 5.3.1
JDK : Oracle 10.0.2 (happens under 8 and OpenJDK 11.0.1 too)
IntelliJ : 2018.3 EAP
testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.3.1'
testRuntime group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.3.1'
testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '2.23.0'
Actual Question:
I had some questions regarding use cases of new “Strict” stubbing.
With Junit5 & @ExtendWith(MockitoExtension.class)
I’ve noticed that it errors out when I think it shouldn’t (when compared with Junit4 & @RunWith(MockitoJUnitRunner.class)
)
I have a very simple test case, which I consider to be both good code, and good mocking. Which gets highlighted as incorrect stubbing usage under Strict (default) checking
package com.example;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class MockitoTest {
@Mock
private Map<String, Object> mockMap;
@Mock
private Object mockObject;
@Test
void shouldBeAbleToMock() {
// When
when(mockMap.get("A")).thenReturn("Apple");
when(mockMap.get("B")).thenReturn(mockObject);
// Then
assertEquals("Apple", mockMap.get("A"));
assertEquals(mockObject, mockMap.get("B"));
}
}
The above gives the following stacktrace when run:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'get' method:
mockMap.get("B");
-> at com.example.MockitoTest.shouldBeAbleToMock(MockitoTest.java:25)
- has following stubbing(s) with different arguments:
1. mockMap.get("A");
-> at com.example.MockitoTest.shouldBeAbleToMock(MockitoTest.java:24)
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.
at com.example.MockitoTest.shouldBeAbleToMock(MockitoTest.java:25)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:515)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:105)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I’ve found 1 other reference to this issue online, which was here: https://stackoverflow.com/questions/52139619/simulation-of-service-using-mockito-2-leads-to-stubbing-error
The above stated you could work around the issue by changing the code as follows:
// From this
when(mockMap.get("A")).thenReturn("Apple");
when(mockMap.get("B")).thenReturn(mockObject);
// To this
when(mockMap.get(anyString())).thenAnswer(invocation -> {
Object arg = invocation.getArgument(0);
if ("A".equals(arg)) return "Apple";
if ("B".equals(arg)) return system;
});
Is this a bug, or is this intentional going forwards?
Thanks for your time!
check that
- [✓] The mockito message in the stacktrace have useful information, but it didn’t help
- [✓] The problematic code (if that’s possible) is copied here; Note that some configuration are impossible to mock via Mockito
- [✓] Provide versions (mockito / jdk / os / any other relevant information)
- [✓] Provide a Short, Self Contained, Correct (Compilable), Example of the issue (same as any question on stackoverflow.com)
- [✓] Read the contributing guide
Issue Analytics
- State:
- Created 5 years ago
- Comments:8
Top GitHub Comments
@BrentMeeusen in fact in my case the solution was the use of equals and hashcode, thank you very much.
Finding exactly the same issue as described above using
@RunWith(MockitoExtension.class)
version 5.3.2 of the above dependencies and
@hjohn @bwhiting2356 @jmart1 be interested to hear how you resolved this…