当看起来没问题时,Mockito会给出UnfinishedVerificationException

Jon*_*han 37 junit unit-testing mockito junit5

UnfinishedVerificationException当我认为我已经完成了所有事情时,Mockito似乎正在投掷.这是我的部分测试用例:

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());
Run Code Online (Sandbox Code Playgroud)

这是部分类和方法:

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

忽略你不应该模仿你不拥有的接口的事实,为什么Mockito给我以下信息?

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
Run Code Online (Sandbox Code Playgroud)

Ste*_*oss 58

我刚刚遇到了这个我的自我,这给我带来了很多困惑.

正如David上面提到的,Mockito报告了下一个 Mockito方法调用中的错误,这可能不是在同一个测试方法中.虽然异常消息确实包含对错误发生的实际位置的引用,但我发现错误的测试无法对测试过程产生反作用.而且测试越简单,错误就越有可能出现在下一次测试中!

这是一个简单的修复,可以确保错误出现在正确的测试方法中:

@After
public void validate() {
    validateMockitoUsage();
}
Run Code Online (Sandbox Code Playgroud)

这里的Mockito文档:

如果您滥用它,Mockito会抛出异常,以便您知道您的测试是否正确编写.问题是Mockito下次使用框架时会进行验证(例如,下次验证时,存根,调用模拟等).但即使可能在下一个测试中抛出异常,异常消息也包含一个带有缺陷位置的可导航堆栈跟踪元素.因此,您可以点击并找到Mockito被滥用的地方.

有时,您可能希望明确验证框架使用情况.例如,其中一个用户希望将validateMockitoUsage()放入他的@After方法中,这样他就会立即知道何时滥用Mockito.如果没有它,他会在下次使用框架之前就知道它.在@After中使用validateMockitoUsage()的另一个好处是,jUnit运行器将始终在测试方法中出现故障, 而普通的"下次"验证可能会使下一个测试方法失败.但即使JUnit可能会将下一个测试报告为红色,也不要担心它,只需单击异常消息中的可导航堆栈跟踪元素即可立即找到您滥用mockito的位置.


Bab*_*yan 51

如果您尝试使用verify以下原始参数的方法,也可能会导致这种情况any():

例如,如果我们的方法有这个签名:

method(long l, String s);
Run Code Online (Sandbox Code Playgroud)

并且您尝试像这样验证它,它将失败并带有上述消息:

verify(service).method(any(), anyString());
Run Code Online (Sandbox Code Playgroud)

将其更改为anyLong(),它将工作:

verify(service).method(anyLong(), anyString());
Run Code Online (Sandbox Code Playgroud)

  • 投票,因为这就是发生在我身上的事情。错误消息没有提到 any() 不能匹配原语。 (4认同)
  • 这正是发生在我身上的事 (2认同)
  • 谢谢!这解决了我的问题。该错误消息确实被误导了。 (2认同)

Mat*_*ein 12

由于any()boolean参数一起使用,我遇到了同样的错误,而显然它需要是anyBoolean().


hta*_*oya 7

就我而言,使用kotlin是因为要测试的函数未声明为open.

异常表明不能final使用 /private/equals/hash 方法。

fun increment(){
        i++
    }
Run Code Online (Sandbox Code Playgroud)

open fun increment(){
        i++
    }
Run Code Online (Sandbox Code Playgroud)


s1m*_*nw1 5

使用 Junit 5,您可以添加以下内容以在控制台中显示更有意义的 Mockito 异常

@AfterEach
public void validate() {
    validateMockitoUsage()
}
Run Code Online (Sandbox Code Playgroud)

另请参阅此答案:/sf/answers/1578503881/