简体   繁体   English

Mockito,方法验证的任务

[英]Mockito, mission of method verify

Could you please explain a mission of mockito method verify? 您能否解释一下模拟方法验证的任务? Documentation says, that this method checks, whether the method was called. 文档说,此方法检查是否调用了该方法。 But can you give an example when it is really useful? 但是,当它真正有用时,您可以举一个例子吗? Usually in test method we invoke a method and then... check, that we have invoked it right now? 通常在测试方法中,我们先调用一个方法,然后...检查是否已经立即调用了它? Sounds weird. 听起来怪怪的。

It goes like this: 它是这样的:

public class UnderTest {
  private Foo foo;

  public UnderTest(Foo foo) { this.foo = foo };

  public void bar() { foo.foo(); }
}

Now assume that you provide a mocked foo instance to UnderTest. 现在,假设你提供嘲笑富实例UnderTest。 And you want to be sure that foo.foo() is invoked when bar() is called. 并且您想确保在调用bar()时调用了foo.foo()

Then you use verify() to ensure that the expected call took place. 然后,使用verify()来确保进行了预期的调用。

In other words: tests need to verify method behavior. 换句话说:测试需要验证方法的行为。 Ideally they do that by asserting on values returned by the method under test. 理想情况下,它们通过声明被测方法返回的值来做到这一点。 But not all methods return something. 但是,并非所有方法都返回某些东西。 Then you might verify your code by at least checking that certain expected calls on objects owned/passed to the class under test did occur. 然后,您可以通过至少检查是否确实对拥有/传递给被测类的对象进行了某些预期的调用验证代码。 And then you need verify() ! 然后,您需要verify()

This type of check is often performed just to make sure that specific object was used using specified parameters. 通常执行这种类型的检查只是为了确保使用指定的参数来使用特定的对象。 Let's assume You are testing business service that performs some action and also some kind of audit trail is being stored in DB during this process. 假设您正在测试执行某些操作的业务服务,并且在此过程中还将某种审计跟踪存储在数据库中。

Storing that kind of info in DB was already tested somewhere else (separate unit-tests or some kind of external library is used), so You do not need checking whether audit data was stored properly. 将这种信息存储在数据库中已经在其他地方进行了测试(使用了单独的单元测试或某种外部库),因此您无需检查审计数据是否正确存储。 For the sake of Your test-case the information that this method was called is sufficient. 为了您的测试用例,调用此方法的信息就足够了。 And that's the use case for 'verify' method. 这就是“验证”方法的用例。

Usually in test method we invoke a method and then... check, that we have invoked it right now? 通常在测试方法中,我们先调用一个方法,然后...检查是否已经立即调用了它? Sounds weird. 听起来怪怪的。

You don't verify that you invoked a test method. 您不验证您是否调用了测试方法。 You verify that as a result of whatever that test did, some dependency (that you have replaced with a mock) was called. 您验证由于该测试所做的任何结果,都调用了某些依赖项(已由模拟替换)。

So for example, when testing a password checker method, you want to assert that in addition to rejecting the incorrect password it also calls some auditing backend system to register the failed login attempt. 因此,例如,在测试密码检查器方法时,您想断言,除了拒绝不正确的密码之外,它还调用某些审核后端系统来注册失败的登录尝试。 Your mock object would stand in for that backend system, and you can use it to verify that it ended up being called (and also with the proper parameters). 模拟对象将代表该后端系统,您可以使用它来验证它是否最终被调用(并带有适当的参数)。

To simplify... Let's say you are testing method A with certain parameters. 为了简化...假设您正在使用某些参数测试方法A。 What method A does is calls methods B , C and D . 方法A所做的就是调用方法BCD。

With Mockito.verify you can test that methods B, C, D really are called. 使用Mockito.verify,您可以测试方法B,C,D是否真正被调用。 It even let's you specify more complex testing such as: 它甚至让您指定更复杂的测试,例如:

  • atLeast(1) 至少(1)
  • atMost(10) atMost(10)

It can really be useful when the method you are testing behaves differently based on parameters you call it with. 当您要测试的方法根据调用它的参数而表现不同时,它确实很有用。

Let's imagine that you have some DAO class which interacts with the database by plain JDBC. 假设您有一些DAO类,它通过纯JDBC与数据库交互。 You have some method to write data in the database and want to unit test it. 您有一些方法可以在数据库中写入数据并要对其进行单元测试。 To do so, you probably mock Connection class. 为此,您可能要模拟Connection类。 When you're writing in the database you will probably call commit method on this mock, but the return type of it is void , so you can't guarantee that that method invoked during your test. 当您在数据库中编写代码时,您可能会在此模拟上调用commit方法,但是其返回类型为void ,因此您不能保证在测试期间会调用该方法。 To solve such problems you can use verify . 要解决此类问题,您可以使用verify Hope it helps! 希望能帮助到你!

Methods return either something or void . 方法返回的东西或void
In unit test, as a method returns something, generally you want to mock its result with a specific value and check that the flow of the tested method goes on as it should. 在单元测试中,当一种方法返回某些东西时,通常您希望使用特定的值来模拟其结果,并检查被测试方法的流程是否按预期进行。
It makes sense as if a method to mock returns something, generally you need its results : either in the next statement of the tested method or in the result returned by the tested method. 好像要模拟的方法返回一些东西是有道理的,通常您需要它的结果:在测试方法的下一个语句中或在测试方法返回的结果中。

As a method returns nothing ( void ), things are different : you cannot mock its result. 由于方法不返回任何内容( void ),因此情况有所不同:您无法模拟其结果。
But you can assert that this method is invoked and with expected parameters. 但是您可以断言此方法已调用并且具有预期参数。

For example imagine a PrinterService class to print documents 例如,假设使用PrinterService类来打印文档

public class PrintService{
 ...
  public void printMessage(String message){
    os.print(message);
  }
}

And suppose you need to isolate it during an unit test of another class. 并且假设您需要在另一个类的单元测试期间将其隔离。
Here the method to test : 这里测试方法:

public class PrintClient{
 ...
  PrintService printService;

  public void print(String message, PrinterParameters printerParameters...){
     ... // do some tasks
     ...
     printService.print(message);
    ...          
  }
}

PrintService.print() returns nothing. PrintService.print()返回任何内容。
So in the unit test of PrintClient , you don't want to mock the result of PrintService.print() as it doesn't have. 因此,在PrintClient的单元测试中,您不想模拟PrintService.print()的结果,因为它没有。
You want just to check that it was invoked with the message argument passed to to the PrintClient tested method. 您只想检查是否已通过传递给PrintClient测试方法的message参数调用了它。

@RunWith(MockitoJUnitRunner.class) 
public class PrintClientTest{

    @Mock 
    PrintService printServiceMock;
    ...
    @Test
    pubic void print(){
      ... 
      String message = "my message";  
      PrintClient printClient = new PrintClient(printServiceMock);
      printClient.print(message, ...);
      //
      Mockito.verify(printServiceMock).print(message);
      ...
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM