Mockito:在没有@RunWith的情况下启用框架使用验证(MockitoJUnitRunner.class)

时间:2016-12-08 17:34:27

标签: java unit-testing junit mockito testng

我们正在使用Testng 6.8.8 + Mockito 1.10.19,显然我们不能使用MockitoJUnitRunner,但验证框架仍然有效! 在这篇thread中,我读到它不应该是这种情况。谁能解释一下?这是因为我们还有@Before *回调和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将告诉我有关匹配器使用不正确的信息。

我也可以这样做:

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)

1 个答案:

答案 0 :(得分:3)

Matchers work via side-effects and static global state,所以你可以把这个电话分成几部分来看看发生了什么。

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

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

在init [1]之后,Java看到对any [2-5]的四次调用以及对transform [6]的一次调用。但是,Mockito只能看到对any的四次调用;因为mealTransformer不是模拟,Mockito无法看到它的调用。如果您单独运行该测试,Mockito将留下四个未消耗的记录匹配器。 JVM会拆除测试框架,测试将传递 - ,除非您在validateMockitoUsage方法中调用了@After,这将完全捕捉到这种情况。< / p>

但是,当你进行两次测试时,它们会像这样叠加:

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中滥用匹配器而失败。在validateMockitoUsage消息中使用@After后,您将获得相应的测试失败。