Mockito - 使用 Maven 运行时出现 InvalidUseOfMatchersException,但直接从 Eclipse 工作

问题描述 投票:0回答:3

我有用于休息通话的模拟方法。

public void createRestClientMock() {
        org.mockito.Mockito.when(
                restClient.sendResponse(org.mockito.Matchers.anyString(),
                        org.mockito.Matchers.anyString())).thenAnswer(
                new Answer<Object>() {
                    public Object answer(InvocationOnMock invocation) {
                        Object[] args = invocation.getArguments();
                        actualResponse = args[1].toString();
                        LOG.debug(actualResponse);
                        return null;
                    }
                });
    }

真正的方法按照预期被嘲笑,当我从 eclipse 运行 junit 时,一切都工作正常。

但是当我尝试使用 Maven 构建从 Jenkins 运行 junit 时,我收到以下错误:-

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced argument matcher detected here:

-> at uk.co.common.Test.createRestClientMock(Test.java:166)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
    verify(mock).someMethod(contains("foo"))

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.

添加依赖项

<dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.0.13-beta</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>1.3</version>
            <scope>test</scope>
        </dependency>
java maven jenkins junit mockito
3个回答
1
投票

我遇到了同样的问题,结果是因为 maven-surefire-plugin 试图使用 JUnit3 运行程序而不是 JUnit4,导致 @RunWith(MockitoJUnitRunner.class) 注释被忽略。 有几个潜在的原因,例如:

  • 类路径中同时具有 JUnit3 和 JUnit4。

  • 使用与类路径中存在的不同的路径。

就我而言,我正在升级一个现有项目,并将 junit:junit-dep 替换为 junit:junit,但没有意识到 pom 中的 Surefire 配置有 junit:junit-dep。 Eclipse 会忽略 POM 中的任何内容,并默认创建 JUnit4 配置,因此在使用 Run As...JUnit 测试运行时,所有测试都会通过。


0
投票

同样的错误也发生在我身上,我正在互联网上进行搜索。但后来我仔细的看到了控制台上的maven日志。

我在其他一些测试用例中犯了一个错误,该错误没有显示在控制台上。 junit 测试如下。

    @Test
    void testUpdateLookupDataException() {
        Mockito.doNothing().when(dataHubService).updateSpecifiedLookUpTables(Mockito.any());
        try {
            controller.updateSpecifiedLookUpTables(Mockito.anyList());
            Assertions.fail();
        } catch (Exception e) {
            Assertions.assertEquals("Please provide mapping entities", e.getMessage());
        }
        
    }

上面的测试在 Eclipse 中运行良好,但在控制台中我在顶部得到了错误。在控制台末尾,错误有所不同。我正在分享机器人从上到下的屏幕截图。

head

bottom

如果您看到这两个屏幕截图,那就有点误导了。我试图修复“testHandleConflict”方法中的测试,但实际错误是在“testUpdateLookupDataException”测试中。

解决方案不是使用“Mockito.anyList()”,而是我应该使用实际列表。


-1
投票

您的方法看起来正确,并且可以正确地单独运行。这意味着 您的错误可能是在作为同一 Maven 套件的一部分运行的不同方法中

Mockito 匹配器并不纯粹是功能性的:在幕后有一个 ThreadLocal 匹配器堆栈,为下一次存根或验证调用保存。 Mockito 匹配器调用添加到此堆栈并返回虚拟值。但是,Mockito 无法非常仔细地监管此堆栈,因为它无法分析或预测匹配器调用是否使用正确或不正确,直到测试结束,此时它没有抛出异常所需的控制权。 这意味着在同一 JVM 中运行一系列基于 Mockito 的测试时,Matchers 特别容易受到测试污染。

单独运行测试或使用不同的套件运行程序(Maven 与 Eclipse)时,您的测试可以正常运行。对你来说不幸的是,Maven 对你的测试进行了排序,因此损坏的测试先于你上面发布的测试。请注意,“损坏的测试”仍然通过;它只会使 Matcher 堆栈处于错误状态,从而导致正确的测试失败。


要诊断您的问题,请使用 MockitoJUnitRule 初始化您的测试。它将自动处理 @Mock/@Spy/@Captor 初始化(替换

MockitoAnnotations.initMocks(this)
),重要的是,它将在每次测试结束时调用
Mockito.validateMockitoUsage()
。如果 Matcher 堆栈为空或者任何存根或验证调用不完整,
validateMockitoUsage
会抛出异常;运气好的话,被破坏的测试将会失败,从而确保您的上述正确测试通过。

(如果你不能使用

MockitoJUnitRule
,请回退到 JUnit4 运行程序 MockitoJUnitRunner,它的功能与 MockitoJUnitRule 相同,但与其他运行程序或规则的配合效果不佳。当然,你也可以调用
validateMockitoUsage 
直接,如果您使用 JUnit3 或者您需要确定方法中的何处滥用了匹配器,这可能会派上用场。)

如果您发现匹配器被误用,并且想更好地理解它,这可能是另一个 SO 问题的好主题。

© www.soinside.com 2019 - 2024. All rights reserved.