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

时间:2016-01-10 09:03:00

标签: java maven jenkins junit mockito

我有休息电话的模拟方法。

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 build从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>

2 个答案:

答案 0 :(得分:1)

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

  • 在类路径中同时包含JUnit3和JUnit4。

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

在我的情况下,我提升了一个现有的项目并取代了junit:junit-dep和junit:junit而没有意识到我的确保配置在pom中有junit:junit-dep。 Eclipse忽略POM中的任何内容,默认情况下会创建一个JUnit4配置,因此所有测试都在使用Run As ... JUnit test运行时传递。

答案 1 :(得分:-1)

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

Mockito匹配器并非纯粹的功能:在幕后有一个ThreadLocal堆栈的匹配器保存用于下一个存根或验证调用。 Mockito matcher calls add to this stack and return dummy values.但是,Mockito无法非常谨慎地监控此堆栈,因为它无法分析或预测在测试结束之前是否正确或错误地使用了匹配器调用,此时它没有控制它需要抛出异常。 这意味着在同一个JVM中运行一系列基于Mockito的测试时,Matchers特别容易受到测试污染。

单独运行测试或使用不同的套件运行程序(Maven vs Eclipse)时,您的测试工作正常。不幸的是,Maven订购了你的测试,所以破坏的测试先于你上面发布的测试。请注意,“破损测试”仍然通过;它只会使Matcher堆栈处于错误状态,这会导致您的正确测试失败。

要诊断问题,请使用MockitoJUnitRule初始化测试。它将自动处理@Mock / @ Spy / @ Captor初始化(替换MockitoAnnotations.initMocks(this)),重要的是,它将在每次测试结束时调用Mockito.validateMockitoUsage()。如果Matcher堆栈为空或者任何存根或验证调用不完整,则validateMockitoUsage会抛出异常;如果幸运的话,破损的测试将会失败,确保您的正确测试通过。

(如果你不能使用MockitoJUnitRule,请回到JUnit4跑步者MockitoJUnitRunner,它与MockitoJUnitRule一样,但与其他跑步者或规则不同。当然,您也可以直接致电validateMockitoUsage,如果您使用的是JUnit3,可能会派上用场,或者您需要确定某种方法中您滥用匹配器的位置。)

如果您发现您的匹配器被滥用,并希望更好地理解它,那么这可能是另一个SO问题的好主题。