@RunWith(MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks(this)

2022-08-31 08:03:39

在编写新的jUnit4测试时,我想知道是否要使用或.@RunWith(MockitoJUnitRunner.class)MockitoAnnotations.initMocks(this)

我创建了一个新的测试,向导使用Runner自动生成了一个测试。Javadocs for MockitoJUnitRunner 声明如下:

与 JUnit 4.4 及更高版本兼容,此运行器添加了以下行为:

初始化用 Mock 注释的 mock,这样就不需要显式使用 MockitoAnnotations.initMocks(Object)。在每个测试方法之前初始化模拟。在每个测试方法之后验证框架使用情况。

我不清楚使用Runner是否比我过去使用的方法有任何优势。initMocks()


答案 1

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

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

  • 调用静态方法,但不要使用匹配的 或 完成存根。(以下代码中的错误 1)whenthenReturnthenThrowthen

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

  • 在 之后调用该方法,或者 并传递一个 mock,但忘记提供您尝试存根的方法。(以下代码中的错误 3)whendoReturndoThrowdoAnswer

如果没有对框架使用情况的验证,则在以下对 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. 
}

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

因此,我建议尽可能使用。但是,正如Tomasz Nurkiewicz正确指出的那样,如果您需要另一个JUnit跑步者,例如Spring跑步者,则无法使用它。MockitoJUnitRunner

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

包括

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

在测试类中。这将初始化模拟,并自动执行框架验证;就像这样。但现在,您也可以使用或任何其他JUnitRunner。从Mockito 2.1.0开始,还有其他选项可以精确控制报告的问题类型。MockitoJUnitRunnerSpringJUnit4ClassRunner


答案 2

使用运行器可以节省一点编码(不需要方法)。另一方面,使用跑步者有时是不可能的,也就是说,当你已经在使用一个跑步者时,比如SpringJUnit4ClassRunner@Before

就是这样。这只是一个偏好问题。


推荐