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

Oce*_*lue 98 java junit4 mockito

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

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

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

初始化用Mock注释的模拟,因此不需要明确使用MockitoAnnotations.initMocks(Object).在每种测试方法之前初始化模拟.验证每个测试方法后的框架使用情况.

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

任何想法或链接将不胜感激!

Daw*_*ica 125

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

框架使用的自动验证实际上值得拥有.如果您犯下其中一个错误,它会为您提供更好的报告.

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

  • 你调用verifymock,但忘记提供你要验证的方法调用.(以下代码中的错误2)

  • 你在when之后调用方法doReturn,doThrow或者 doAnswer传递一个模拟,但忘记提供你试图存根的方法. (以下代码中的错误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. 
}
Run Code Online (Sandbox Code Playgroud)

我五年前写这篇答案的时候已经写过了

所以我建议MockitoJUnitRunner尽可能使用.但是,正如Tomasz Nurkiewicz正确指出的那样,如果你需要另一个JUnit运行器,你就不能使用它,比如Spring.

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

包括

@Rule 
public MockitoRule rule = MockitoJUnit.rule();
Run Code Online (Sandbox Code Playgroud)

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

  • @alexandroid我最好的建议是你使用“@ExtendWith”编写自己的答案。这确实不是我所知道的事情。Stack Overflow 的伟大之处在于,对于这样的问题,你最终可以得到多个正确答案。 (2认同)

Tom*_*icz 24

使用runner可以节省一些编码(不需要@Before方法).另一方面,使用跑步者有时是不可能的,即当你已经使用跑步者时,比如SpringJUnit4ClassRunner.

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

  • 除了 initMocks() 行之外,任何其他设置仍然需要 @Before 方法,对吗? (2认同)
  • @OceanBlue:当然,如果您的@Before方法包含除initMocks()之外的任何内容,则在迁移到运行程序之后必须保留它。 (2认同)
  • 我正在使用 Spring Boot,我可以说`SpringJUnit4ClassRunner` 会自动为我初始化模拟。不过,我不知道普通的春天。 (2认同)