为什么我们在junit测试中使用Mockitojunitrunner类?

时间:2017-06-28 05:39:53

标签: java junit mockito

我是mockito框架的新手,我对此有一个非常基本的问题,为什么我们在junit测试类中使用 MockitoJunitRunner类。此外,我发现以下两点与此相关但无法得到它,任何人都可以详细解释以下两点

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

  • 您在模拟上调用verify,但忘记提供方法调用 你正试图验证。
  • 您可以调用when方法之一(静态方法或方法) 在doReturn,doThrow或doAnswer之后)并通过模拟,但忘了 提供您尝试存根的方法。

1 个答案:

答案 0 :(得分:6)

使用MockitoJunitRunner而非JunitRunner实际上是可选的。

  

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

MockitoJunitRunner提供的主要优势是让您在使用MockitoAnnotations.initMocks(Object)方式创建模拟时明确调用@Mock

但是你可以通过使用这个可能在不使用它的情况下丢失的跑步者来获得更多关于Mockito框架的滥用报告。

Mockito 1.10.19版本的javadoc声明:

  

与JUnit 4.4及更高版本兼容,此跑步者增加了以下内容   行为:

     
      
  • 初始化用Mock注释的模拟,以便明确使用   MockitoAnnotations.initMocks(Object)没有必要。模拟是   在每种测试方法之前初始化。

  •   
  • 在每个测试方法之后验证框架使用情况。请参阅javadoc   Mockito.validateMockitoUsage()。

  •   

最重要的部分:

  

Runner是完全可选的 - 还有其他方法可以获得@Mock   工作,例如通过编写基类。 明确验证   框架使用也是可选的,因为它是自动触发的   每次使用框架时都由Mockito提供。请参阅javadoc for   Mockito.validateMockitoUsage()

在不使用MockitoJunitRunner的情况下可以开箱即用的错误使用示例:

 //Oops, thenReturn() part is missing:
 when(mock.get());

 //Oops, verified method call is inside verify() where it should be on the outside:
 verify(mock.execute());

 //Oops, missing method to verify:
 verify(mock);

但在所有情况下都无法捕捉到这些。

由跑步者和框架本身调用的Mockito.validateMockitoUsage()方法提供了更多关于它的解释,但实际上它并不完整。

  

validateMockitoUsage()显式验证框架状态为   检测Mockito的无效使用。但是,此功能是可选的   因为Mockito一直在验证用法... 但是有一个   如此阅读

确定。继续。

  如果你滥用它,Mockito会抛出异常,以便你知道你的   测试写得正确。问题是,Mockito做了   验证下次您使用框架(例如,下次验证时,   存根,调用模拟等)。但即使异常可能被抛出   在下一个测试中,异常消息包含一个可导航的堆栈   跟踪元素与缺陷的位置。因此你可以点击和   找到Mockito被滥用的地方。

因此,框架在您下次使用框架时进行验证(验证,存根,调用模拟等)。
事实上这是真的,但并非总是如此。

例如,这种滥用将被框架捕获:

@Test
public void testBadUseWhen() throws Exception {
   Address mock = Mockito.mock(Address.class);
   Mockito.verify(mock.getAddressLine());
}
  

org.mockito.exceptions.misusing.NullInsteadOfMockException:参数   传递给verify()应该是一个mock但是为null!

但这种误用不会被抓住:

@Test
public void testBadUseWhen() throws Exception {
  Address mock = Mockito.mock(Address.class);
  Mockito.when(mock.getAddressLine());
}

如果我在未被滥用的情况下添加了Mockito的新用法,那么这次我们将获得验证例外:

@Test
public void testBadUseWhen() throws Exception {
    Address mock = Mockito.mock(Address.class); 
    Mockito.when(mock.getAddressLine());
    Mockito.when(mock.getAddressLine());
}
  

org.mockito.exceptions.misusing.UnfinishedStubbingException:   这里检测到未完成的短截

将调用第二个Mockito.when(mock.getAddressLine());语句,但异常将引用调用的第一个Mockito.when(mock.getAddressLine());语句。

这意味着对于框架的一些不良用途,如果您使用的最后一个mockito方法使用不当,您可能会丢失报告信息。

然后javadoc声明:

  

有时候,您可能希望验证框架使用情况   明确。例如,其中一个用户想要放置   validateMockitoUsage()在他的@After方法中,以便他知道   当他误用Mockito时。没有它,他就会知道   关于它不早于下次他使用框架。多一个   在@After中使用validateMockitoUsage()的好处就是jUnit   在有缺陷的测试方法中,运行器和规则总是会失败   而普通的“下一次”验证可能会失败下一次测试   方法。但即使JUnit可能会将下一个测试报告为红色,也不要   担心它,只需单击中的可导航堆栈跟踪元素   异常消息,可以立即找到您滥用的地方   的Mockito。

因此,为了避免在测试类中调用的最后一个Mockito方法失去可能的误用,您可以在每个测试方法之后显式调用Mockito.validateMockitoUsage()

所以这将解决问题:

@After
public void after() {
    Mockito.validateMockitoUsage();
}

另一种方法是在每次执行测试后使用引擎盖下调用MockitoJUnitRunner的{​​{1}}:

Mockito.validateMockitoUsage()