java - @RunWith(MockitoJUnitRunner.class) 与 MockitoAnnotations.initMocks(this)

标签 java junit4 mockito

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

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

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.

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

最佳答案

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

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

  • 您调用静态 when 方法,但未使用匹配的 thenReturnthenThrow 完成 stub >然后(下面代码中的错误 1)

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

  • 您在 doReturndoThrowdoAnswer 并传递一个模拟,但忘记提供该方法 你正在尝试 stub 。 (下面代码中的错误 3)

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

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

So I would recommend the use of the MockitoJUnitRunner wherever possible. However, as Tomasz Nurkiewicz has correctly pointed out, you can't use it if you need another JUnit runner, such as the Spring one.

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

包括

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

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

关于java - @RunWith(MockitoJUnitRunner.class) 与 MockitoAnnotations.initMocks(this),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10806345/

相关文章:

java - 如何在抛出异常后促使应用程序继续运行?

java - JAX-RS:如何保护 REST 端点?

java - JavaFX 中的透明 Accordion 背景

java - 为测试加载系统属性

java - 如何使用 Mockito 对返回的模拟对象进行断言

mockito - 模拟投影结果 Spring Data JPA

java - PowerMockito 模拟静态方法抛出 UnfinishedStubbingException

使用 Linux 终端运行命令的 Java 程序

java - MockitoInvocationHandler 类的 NoClassDefFoundError

java - NPE 引起的 Mockito ExceptionInInitializerError