我有用于休息通话的模拟方法。
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>
我遇到了同样的问题,结果是因为 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 测试运行时,所有测试都会通过。
同样的错误也发生在我身上,我正在互联网上进行搜索。但后来我仔细的看到了控制台上的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 中运行良好,但在控制台中我在顶部得到了错误。在控制台末尾,错误有所不同。我正在分享机器人从上到下的屏幕截图。
如果您看到这两个屏幕截图,那就有点误导了。我试图修复“testHandleConflict”方法中的测试,但实际错误是在“testUpdateLookupDataException”测试中。
解决方案不是使用“Mockito.anyList()”,而是我应该使用实际列表。
您的方法看起来正确,并且可以正确地单独运行。这意味着 您的错误可能是在作为同一 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 问题的好主题。