135

While writing a new jUnit4 test, I'm wondering whether to use @RunWith(MockitoJUnitRunner.class) or MockitoAnnotations.initMocks(this).

I created a new test & the wizard automatically generated a test with the Runner. Javadocs for MockitoJUnitRunner state the following:

Compatible with JUnit 4.4 and higher, this runner adds following behavior:

Initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks are initialized before each test method. Validates framework usage after each test method.

It's not clear to me whether using the Runner has any advantage over the initMocks() method I have been using in past.

4

2 回答 2

169

MockitoJUnitRunner为您提供框架使用的自动验证,以及自动initMocks().

框架使用的自动验证实际上是值得拥有的。如果您犯了这些错误之一,它会为您提供更好的报告。

  • 您调用静态when方法,但不要使用匹配的thenReturn,thenThrow或来完成存根then(下面代码中的错误1)

  • 您调用verify了一个模拟,但忘记提供您要验证的方法调用。(以下代码中的错误 2)

  • 您在或 之后调用该when方法doReturn,并传递一个模拟,但忘记提供您尝试存根的方法。 (下面代码中的错误3)doThrowdoAnswer

如果您没有验证框架使用情况,则在以下调用 Mockito 方法之前不会报告这些错误。这可能是

  • 在相同的测试方法中(如下面的错误 1),
  • 在下一个测试方法中(如下面的错误 2),
  • 在下一个测试课上。

如果它们发生在您运行的最后一个测试中(如下面的错误 3),则根本不会报告它们。

以下是每种类型的错误的外观。在这里假设 JUnit 按照它们在此处列出的顺序运行这些测试。

@Test
public void test1() {

    // ERROR 1
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called.
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen.
    when(myMock.method1());

    doSomeTestingStuff();

    // ERROR 1 is reported on the following line, even though it's not the line with
    // the error.
    verify(myMock).method2();

}

@Test
public void test2() {

    doSomeTestingStuff();

    // ERROR 2
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call to verify.  But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen.
    verify(myMock);
}

@Test
public void test3() {

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error.
    doReturn("Hello").when(myMock).method1();


    // ERROR 3
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call is being stubbed.  But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen.

    doReturn("World").when(myMock);

    doSomeTestingStuff(); 

    //  ERROR 3 is never reported, because there are no more Mockito calls. 
}

现在,当我五年多前第一次写这个答案时,我写了

所以我建议MockitoJUnitRunner尽可能使用。但是,正如 Tomasz Nurkiewicz 正确指出的那样,如果您需要另一个 JUnit 运行程序,例如 Spring 运行程序,则不能使用它。

我的建议现在已经改变。自从我第一次写这个答案以来,Mockito 团队添加了一个新功能。这是一个 JUnit 规则,它执行的功能与MockitoJUnitRunner. 但它更好,因为它不排除使用其他跑步者。

包括

@Rule 
public MockitoRule rule = MockitoJUnit.rule();

在你的测试课上。这会初始化模拟,并自动执行框架验证;就像MockitoJUnitRunner那样。但是现在,您也可以使用SpringJUnit4ClassRunner或任何其他 JUnitRunner。从 Mockito 2.1.0 开始,还有一些额外的选项可以准确控制报告的问题类型。

于 2012-05-30T08:36:03.110 回答
29

使用 runner 可以让你节省一点编码(不需要@Before方法)。另一方面,有时无法使用跑步者,即当您已经在使用跑步者时,例如SpringJUnit4ClassRunner.

而已。这只是一个偏好问题。

于 2012-05-29T20:40:51.640 回答