Search code examples
unit-testingjunitmockitojunit5

Mockito gives UnfinishedVerificationException when it seems OK


Mockito appears to be throwing an UnfinishedVerificationException when I think I've done everything correctly. Here's my partial test case:

HttpServletRequest req = mock(HttpServletRequest.class);
when(req.getHeader("Authorization")).thenReturn("foo");

HttpServletResponse res = mock(HttpServletResponse.class);

classUnderTest.doMethod(req, res); // Use the mock

verify(res, never());
verify(req).setAttribute(anyString(), anyObject());

And here's the partial class and method:

class ClassUnderTest extends AnotherClass {
    @Override
    public String doMethod(ServletRequest req, ServletRequest res) {
        // etc.
        return "someString";
    }
}

Ignoring the fact that you should never mock interfaces you don't own, why is Mockito giving me the following message?

org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-> at (redacted)

Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.

at [test method name and class redacted]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
... etc

Solution

  • I just came across this my self and it caused me a lot of confusion.

    As David mentioned above Mockito reports errors in the next Mockito method call which may not be in the same test method. While the exception message does contain a reference to the actual place the error occurred I find having incorrect tests failing counter productive to the testing process. And the simpler the tests the more likely an error is to show up in the next test!

    Here is an easy fix that will ensure errors appear in the correct test method:

    @After
    public void validate() {
        validateMockitoUsage();
    }
    

    From the Mockito documentation here:

    Mockito throws exceptions if you misuse it so that you know if your tests are written correctly. The gotcha is that Mockito does the validation next time you use the framework (e.g. next time you verify, stub, call mock etc.). But even though the exception might be thrown in the next test, the exception message contains a navigable stack trace element with location of the defect. Hence you can click and find the place where Mockito was misused.

    Sometimes though, you might want to validate the framework usage explicitly. For example, one of the users wanted to put validateMockitoUsage() in his @After method so that he knows immediately when he misused Mockito. Without it, he would have known about it not sooner than next time he used the framework. One more benefit of having validateMockitoUsage() in @After is that jUnit runner will always fail in the test method with defect whereas ordinary 'next-time' validation might fail the next test method. But even though JUnit might report next test as red, don't worry about it and just click at navigable stack trace element in the exception message to instantly locate the place where you misused mockito.