Mockito:是否在没有@RunWith(MockitoJUnitRunner.class)的情况下启用了框架用法的验证 [英] Mockito: Is validation of framework usage enabled without @RunWith(MockitoJUnitRunner.class)

查看:651
本文介绍了Mockito:是否在没有@RunWith(MockitoJUnitRunner.class)的情况下启用了框架用法的验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用Testng 6.8.8 + Mockito 1.10.19,显然我们不能使用MockitoJUnitRunner,但是验证框架仍然有效! 在此线程中,我读到事实并非如此.有人可以解释吗?这是因为我们还有@Before *回调和MockitoAnnotations.initMocks(this)吗?

We are using Testng 6.8.8 + Mockito 1.10.19 and, obviously we can't use MockitoJUnitRunner, but the validation framework still works! In this thread I read that it should not be the case. Can someone explain? Is this because we still have @Before* callbacks and MockitoAnnotations.initMocks(this)?

我的代码:

public class MealTransformerTest {

MealTransformer mealTransformer = new MealTransformer();

@Test(expectedExceptions = NotImplementedException.class)
public void shouldThrowException() throws NotImplementedException {
    mealTransformer.transform(any(),
            any(),
            any(),
            any());
}

} 在此特定测试中没有任何失败,但是当我运行套件时,Mockito会告诉我有关不正确使用匹配器的信息.

} Nothing fails in this specific test, but when I run the suite, Mockito will tell me about incorrect use of matchers.

我还可以做类似的事情:

I can also do something like:

public class MealTransformerTest {

MealTransformer mealTransformer = new MealTransformer();

//I don't need it in the tests. But I need at least 1 @Mock or @Spy to trigger framework validation
@Mock
private CloneUtils cloneUtils;

@BeforeMethod
void setUp() {
    MockitoAnnotations.initMocks(this);
}


@Test(expectedExceptions = NotImplementedException.class)
public void shouldThrowException() throws NotImplementedException {
    mealTransformer.transform(any(),
            any(),
            any(),
            any());
}

@Test(expectedExceptions = NotImplementedException.class)
public void shouldThrowException123() throws NotImplementedException {
    mealTransformer.transform(any(),
            any(),
            any(),
            any());
}
}

我收到:

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

不要误会我的意思,我真的很喜欢它的工作原理,但是我很惊讶地看到没有@RunWith(MockitoJUnitRunner.class)的情况.

Don't get me wrong, I really like how it works, but I was surprised to see it without @RunWith(MockitoJUnitRunner.class).

推荐答案

匹配器通过副作用和静态全局状态起作用,因此您可以将此次通话分解为多个部分,以了解发生了什么情况.

Matchers work via side-effects and static global state, so you can break this call into pieces to see what's happening.

MockitoAnnotations.initMocks(this);
// in @Before [1]

mealTransformer.transform(any(), any(), any(), any());
//              [6]       [2]    [3]    [4]    [5]

在初始化[1]之后,Java看到对any [2-5]的四个调用和对transform [6]的一个调用.但是,Mockito只看到对any的四个调用;因为mealTransformer不是模拟的,所以Mockito无法看到其调用.如果您单独运行该测试,则Mockito会剩下四个未消耗的记录的匹配器. JVM将拆除测试框架,并且测试将通过- ,除非您在@After方法中对validateMockitoUsage进行了调用,而这恰恰就是这种情况.

After init [1], Java sees four calls to any [2-5] and one call to transform [6]. Mockito, however, only sees the four calls to any; Because mealTransformer is not a mock, Mockito can't see its calls. If you ran that test in isolation, Mockito would be left with four recorded matchers that are not consumed. The JVM would tear down the test framework, and the test would pass—unless you have a call to validateMockitoUsage in an @After method, which would catch exactly that case.

但是,当您有两个测试时,它们会像这样堆积:

When you have two tests, however, they stack up like this:

MockitoAnnotations.initMocks(this);
// [1]
mealTransformer.transform(any(), any(), any(), any());
//              [6]       [2]    [3]    [4]    [5]
// test passes! now the next test
MockitoAnnotations.initMocks(this);
// [7]
mealTransformer.transform(any(), any(), any(), any());
//              [12]      [8]    [9]    [10]   [11]

在这里,步骤7在与步骤1-6相同的JVM中的同一测试执行中发生,这意味着在堆栈上有4个未使用的匹配器时将调用initMocks.这永远都不会发生,因此initMocks会抓住第一个机会来捕获该错误.一种症状是滥用的匹配器异常对应于测试失败的匹配器 :testB由于在testA中滥用了匹配器而失败.在@After消息中使用validateMockitoUsage,您将有适当的测试失败.

Here, step 7 happens in the same test execution in the same JVM as steps 1-6, which means that initMocks is called when there are 4 unconsumed matchers on the stack. This should never happen, so initMocks takes its first opportunity to catch that error. One symptom would be if the misused matcher exception corresponds to a matcher outside of the test that fails: testB failing due to the misuse of a matcher in testA. With the use of validateMockitoUsage in an @After message, you'd have the appropriate test fail instead.

这篇关于Mockito:是否在没有@RunWith(MockitoJUnitRunner.class)的情况下启用了框架用法的验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆