I\'d like to use strict mocks, at least when developing for the first time some tests against old code, so any methods invoked on my mock will throw an exception if I didn\'t sp
Bellow Methods can verify no unexpected method called:
org.mockito.Mockito#only
org.mockito.Mockito#verifyNoMoreInteractions
Add this @Rule
to your test class as a public field:
@RunWith(JUnitParamsRunner.class)
public class MyClassTests {
@Rule
public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Test
....
}
This value was added to Mockito in version 2.3.0
From the documentation:
Ensures clean tests, reduces test code duplication, improves debuggability. Offers best combination of flexibility and productivity. Highly recommended. Planned as default for Mockito v3. Adds following behavior:
- Improved productivity: the test fails early when code under test invokes stubbed method with different arguments (see PotentialStubbingProblem).
- Cleaner tests without unnecessary stubbings: the test fails when unused stubs are present (see UnnecessaryStubbingException).
- Cleaner, more DRY tests ("Don't Repeat Yourself"): If you use Mockito.verifyNoMoreInteractions(Object...) you no longer need to explicitly verify stubbed invocations. They are automatically verified for you.
In addition to the MockitoRule
approach, if you don't need to use a specific test runner (and you are using Mockito 2.5.1 or higher), you could also consider using the MockitoJUnitRunner.StrictStubs
runner, i.e.
@RunWith(MockitoJUnitRunner.StrictStubs.class)
(I would have commented on the post about MockitoRule, but don't have that ability yet)
According to the source code of org.mockito.Mockito.RETURNS_DEFAULTS it selects its "what to do if no expectation" from a global setting. Furthermore "If there is no global configuration then it uses {@link ReturnsEmptyValues} (returns zeros, empty collections, nulls, etc.)" I have not yet been able to make that configuration.
You could use verifyNoMoreInteractions
. It's useful if the tested class catches exceptions.
@Test
public void testVerifyNoMoreInteractions() throws Exception {
final MyInterface mock = Mockito.mock(MyInterface.class);
new MyObject().doSomething(mock);
verifyNoMoreInteractions(mock); // throws exception
}
private static class MyObject {
public void doSomething(final MyInterface myInterface) {
try {
myInterface.doSomethingElse();
} catch (Exception e) {
// ignored
}
}
}
private static interface MyInterface {
void doSomethingElse();
}
Result:
org.mockito.exceptions.verification.NoInteractionsWanted:
No interactions wanted here:
-> at hu.palacsint.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
But found this interaction:
-> at hu.palacsint.CatchTest$MyObject.doSomething(CatchTest.java:24)
Actually, above is the only interaction with this mock.
at hu.palacsint.stackoverflow.y2013.q8003278.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
...
What do you want it to do?
You can set it to RETURN_SMART_NULLS, which avoids the NPE and includes some useful info.
You could replace this with a custom implementation, for example, that throws an exception from its answer
method:
@Test
public void test() {
Object mock = Mockito.mock(Object.class, new NullPointerExceptionAnswer());
String s = mock.toString(); // Breaks here, as intended.
assertEquals("", s);
}
class NullPointerExceptionAnswer<T> implements Answer<T> {
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
throw new NullPointerException();
}
}