65

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());

这是部分类和方法:

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

忽略你永远不应该模拟你不拥有的接口这一事实,为什么 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
4

17 回答 17

103

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

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

method(long l, String s);

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

verify(service).method(any(), anyString());

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

verify(service).method(anyLong(), anyString());
于 2015-06-27T05:24:14.083 回答
82

我刚刚遇到了这个我自己,它给我带来了很多困惑。

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

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

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

从此处的 Mockito 文档:

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

但有时,您可能想要明确地验证框架的使用。例如,其中一位用户希望将 validateMockitoUsage() 放在他的 @After 方法中,以便他在误用 Mockito 时立即知道。没有它,他不会在下次使用该框架时就知道它。在@After 中使用 validateMockitoUsage() 的另一个好处是,jUnit 运行器总是会在有缺陷的测试方法中失败, 而普通的“下一次”验证可能会在下一个测试方法中失败。但即使 JUnit 可能将下一个测试报告为红色,也不必担心,只需单击异常消息中的可导航堆栈跟踪元素即可立即找到您滥用 mockito 的位置。

于 2014-03-21T04:18:01.910 回答
13

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

于 2018-10-18T19:01:39.760 回答
5

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

异常通知不能final使用 /private/equals/hash 方法。

fun increment(){
        i++
    }

open fun increment(){
        i++
    }
于 2020-02-14T16:56:46.317 回答
4

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

@AfterEach
public void validate() {
    validateMockitoUsage()
}

另请参阅此答案:https ://stackoverflow.com/a/22550055/8073652

于 2018-08-09T12:00:20.280 回答
3

对我来说,问题原来是测试上下文 xml 中缺少 bean 声明。它用于另一个类使用的自定义方面类,该类的实例是该类构造函数的参数,该构造函数是失败的 verify() 调用的参数。所以我将 bean 声明添加到上下文 xml 中,之后它工作得很好。

于 2018-01-30T22:18:18.403 回答
2

我的 MyRepository 类有类似的异常

org.mockito.exceptions.misusing.UnfinishedVerificationException:在此处缺少验证(模拟)的方法调用:-> 在 MyRepository$$FastClassBySpringCGLIB$$de8d8358.invoke()

正确验证示例:

verify(mock).doSomething()

当我为 MyRepository 创建接口和模拟接口时,问题得到了解决,但没有实现。似乎 spring 创建了一些 CGLIB 代理,并导致 UnfinishedVerificationException 异常。

于 2016-06-14T07:51:33.257 回答
2

在以下堆栈上,我也遇到了同样的问题:

  • 科特林
  • 朱尼特4.13
  • Mockito 2.28.2+ Mockito-内联2.13.0
  • 机器人电动4.3.1

我试图验证一个 lambda 调用:

@RunWith(RobolectricTestRunner::class)
class MainViewTest {

    @get:Rule
    val mockitoRule: MockitoRule = MockitoJUnit.rule()

    @Mock private lateinit var mockClickCallback: () -> Unit

    @Test
    fun `should call clickCallback on the button click`() {
        val activity = Robolectric.buildActivity(MainActivity::class.java).create().get()
        val viewUnderTest = MainView(activity)
        viewUnderTest.setClickCallback(mockClickCallback)

        viewUnderTest.button.performClick()

        verify(mockClickCallback).invoke() // UnfinishedVerificationException
    }
}

然后我在 Github 上找到了问题,看来问题出在 Robolectric 上。我使用了以下解决方法:

@RunWith(RobolectricTestRunner::class)
class MainViewTest {

    private interface UnitFunction: () -> Unit

    @Test
    fun `should call clickCallback on the button click`() {
        val activity = Robolectric.buildActivity(MainActivity::class.java).create().get()
        val viewUnderTest = MainView(activity)
        val mockClickCallback = mock(UnitFunction::class.java) as () -> Unit
        viewUnderTest.setClickCallback(mockClickCallback)

        viewUnderTest.button.performClick()

        verify(mockClickCallback).invoke() // OK
    }
}
于 2020-06-15T11:37:50.277 回答
0

我有一个类似的问题,我找到了解决这个问题的方法。您要验证的模拟对象尚未重置,因此您应该重置它。您可以在测试用例功能之前重置(模拟) ,这可能会有所帮助。

于 2018-05-03T11:13:21.047 回答
0

如果您尝试使用 Mockito.verify 验证私有或包私有方法,您将收到此错误。

如果您不想使用 PowerMockito,您可以将您的方法设置为受保护,我建议您添加 @VisibleForTesting 标签:

前:

void doSomething() {
   //Some behaviour
}

后 :

@VisibleForTesting
protected void doSomething() {
   //Some behaviour
}
于 2018-11-19T10:26:35.430 回答
0

我有同样的错误

org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-at com.xxx.MyTest.testRun_Should_xxx_When_yyy(MyTest.java:127)

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.
Mocking methods declared on non-public parent classes is not supported.


    at com.xxx.MyTest.validate(MyTest.java:132)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.internal.runners.MethodRoadie.runAfters(MethodRoadie.java:145)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:99)
...

在我的情况下,生成错误是因为我在调用Mockito.verify(...)之前使用了PowerMockito.verifyStatic(),然后我不得不将PowerMockito.verifyStatic()移动到最后一行(或删除它)。

从:

PowerMockito.verifyStatic();
Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class));

到:

Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class)); 
PowerMockito.verifyStatic();
于 2019-07-23T00:28:48.487 回答
0

以上两个答案建议validateMockitoUsage()在每次测试后使用方法。

虽然这是正确的,但我发现@ExtendWith(MockitoExtension.class) 在 Junit 5 中注释您的类会产生相同的效果,同时添加一些不错的 Mockito 功能。此外,它对我来说也看起来更干净。

我猜 Junit 4@RunWith(MockitoJUnitRunner.class)会给出类似的结果,但我没有测试它。

于 2019-11-20T06:52:26.230 回答
0

更改为@RunWith(PowerMockRunner.class),问题就消失了。@RunWith(MockitoJUnitRunner.class)以前用过。

希望对某人有所帮助..

于 2020-02-27T02:14:15.550 回答
0

测试单独运行良好,但在运行集成测试套件时失败并出现 UnfinishedVerificationException。当我们使用 mockito 中的 verify() 并使用 @EnableRetry 时,就会出现问题。解决方法是使用

public static <T> T unwrapAndVerify(T mock, VerificationMode mode) { return ((T) Mockito.verify(AopTestUtils.getTargetObject(mock), mode)); }

如本https://html.developreference.com/article/15741255/Mocked+Spring+%23Service+that+has+%23Retryable+annotations+on+methods+fails+with+UnfinishedVerificationException中所述。

于 2020-07-17T16:19:20.433 回答
0

这是我的一粒盐!我发现MockitoHibernate Validation之间存在冲突。我的解决方案是将我的合同检查(@NotNull、@NotEmpty 等)与模拟测试分开。我也开始使用validateMockitoUsage()以确保一切正常运行。

于 2021-03-09T08:58:47.243 回答
-1

我不确定您的“classUnderTest”来自哪里,但请确保它是模拟的不是真实的。对于下面的测试用例,我有同样的问题:

MyAgent rpc = new MyAgent("myNodeName");
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);

但它在以下测试用例中消失了:

MyAgent rpc = PowerMockito.spy(new MyAgent("myNodeName"));
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);

注意,对象 rpc 应该被PowerMockito.spy(...) 模拟

于 2018-06-13T08:08:49.737 回答
-1

使用 mockStatic 方法并多次调用 Mockito.verify 时遇到相同的异常,但传递的是接口而不是实现类。

错误代码:

try (MockedStatic<Service> staticMock = Mockito.mockStatic(Service.class, Mockito.CALLS_REAL_METHODS)) {
  staticMock.verify(() -> ServiceImpl.method()); // passed without errors
  staticMock.verify(() -> ServiceImpl.method()); // throws UnfinishedVerificationException 
}

固定代码:

try (MockedStatic<ServiceImpl> staticMock = Mockito.mockStatic(Service.class, Mockito.CALLS_REAL_METHODS)) {
  staticMock.verify(() -> ServiceImpl.method());
  staticMock.verify(() -> ServiceImpl.method());
}

这显然是我的错误,但 UnfinishedVerificationException 消息没有帮助

于 2021-04-10T06:07:34.813 回答