Mockito,方法验证的任务
Mockito, mission of method verify
能否请您解释一下 mockito 方法验证的任务?文档说,此方法检查是否调用了该方法。但是在真正有用的时候能举个例子吗?通常在测试方法中我们调用一个方法然后...检查,我们现在已经调用它了吗?听起来很奇怪。
通常执行此类检查只是为了确保使用指定参数使用了特定对象。假设您正在测试执行某些操作的业务服务,并且在此过程中将某种审计跟踪存储在数据库中。
在其他地方已经测试过将这种信息存储在数据库中(使用单独的单元测试或某种外部库),因此您不需要检查审计数据是否正确存储。为了您的测试用例,调用此方法的信息就足够了。这就是 'verify' 方法的用例。
Usually in test method we invoke a method and then... check, that we have invoked it right now? Sounds weird.
您没有验证是否调用了测试方法。您验证作为测试所做的任何结果,调用了一些依赖项(您已用模拟替换)。
因此,例如,在测试密码检查器方法时,您想要断言除了拒绝不正确的密码外,它还会调用一些审计后端系统来注册失败的登录尝试。您的模拟对象将代表该后端系统,您可以使用它来验证它是否最终被调用(以及使用正确的参数)。
它是这样的:
public class UnderTest {
private Foo foo;
public UnderTest(Foo foo) { this.foo = foo };
public void bar() { foo.foo(); }
}
现在假设您向 UnderTest 提供了一个 mocked foo 实例。并且您想 确定 在调用 bar()
时调用 foo.foo()
。
然后您使用 verify() 来确保预期的调用发生。
换句话说:测试需要验证方法行为。理想情况下,他们通过 断言 值 return 通过被测方法来做到这一点。但不是所有的方法return 东西。然后,您 可能 通过至少检查对象 owned/passed 对被测 class 的某些预期调用确实发生来验证您的代码。然后你需要 verify()!
让我们假设您有一些 DAO class,它通过 JDBC 与数据库进行交互。您有一些方法可以将数据写入数据库并希望对其进行单元测试。为此,您可能会模拟 Connection
class。当您在数据库中写入时,您可能会在此 mock 上调用 commit
方法,但它的 return 类型是 void
,因此您不能保证在期间调用该方法你的测试。要解决此类问题,您可以使用 verify
。
希望对您有所帮助!
为了简化...假设您正在使用某些参数测试方法 A。方法A所做的就是调用方法B、C和D。
使用 Mockito.verify 你可以测试方法 B、C、D 是否真的被调用了。它甚至可以让您指定更复杂的测试,例如:
- 至少(1)
- 最多(10)
当您测试的方法根据您调用它时使用的参数表现不同时,它真的很有用。
方法return或者void
。
在单元测试中,作为一种方法 returns 东西,通常你想用一个特定的值模拟它的结果,并检查被测试方法的流程是否按预期进行。
就好像一个模拟returns 东西的方法一样有意义,通常你需要它的结果:在被测试方法的下一个语句中或者在被测试方法的结果return 中。
作为一种方法return什么都不是 (void
),情况有所不同:您不能模拟其结果。
但是您可以断言此方法已被调用并带有预期参数。
例如想象一个 PrinterService
class 来打印文档
public class PrintService{
...
public void printMessage(String message){
os.print(message);
}
}
并且假设您需要在另一个 class.
的单元测试期间隔离它
这里是测试方法:
public class PrintClient{
...
PrintService printService;
public void print(String message, PrinterParameters printerParameters...){
... // do some tasks
...
printService.print(message);
...
}
}
PrintService.print()
return没什么。
所以在 PrintClient
的单元测试中,你不想模拟 PrintService.print()
的结果,因为它没有。
你只想检查它是用传递给的 message
参数调用的
PrintClient
测试方法。
@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);
...
}
}
能否请您解释一下 mockito 方法验证的任务?文档说,此方法检查是否调用了该方法。但是在真正有用的时候能举个例子吗?通常在测试方法中我们调用一个方法然后...检查,我们现在已经调用它了吗?听起来很奇怪。
通常执行此类检查只是为了确保使用指定参数使用了特定对象。假设您正在测试执行某些操作的业务服务,并且在此过程中将某种审计跟踪存储在数据库中。
在其他地方已经测试过将这种信息存储在数据库中(使用单独的单元测试或某种外部库),因此您不需要检查审计数据是否正确存储。为了您的测试用例,调用此方法的信息就足够了。这就是 'verify' 方法的用例。
Usually in test method we invoke a method and then... check, that we have invoked it right now? Sounds weird.
您没有验证是否调用了测试方法。您验证作为测试所做的任何结果,调用了一些依赖项(您已用模拟替换)。
因此,例如,在测试密码检查器方法时,您想要断言除了拒绝不正确的密码外,它还会调用一些审计后端系统来注册失败的登录尝试。您的模拟对象将代表该后端系统,您可以使用它来验证它是否最终被调用(以及使用正确的参数)。
它是这样的:
public class UnderTest {
private Foo foo;
public UnderTest(Foo foo) { this.foo = foo };
public void bar() { foo.foo(); }
}
现在假设您向 UnderTest 提供了一个 mocked foo 实例。并且您想 确定 在调用 bar()
时调用 foo.foo()
。
然后您使用 verify() 来确保预期的调用发生。
换句话说:测试需要验证方法行为。理想情况下,他们通过 断言 值 return 通过被测方法来做到这一点。但不是所有的方法return 东西。然后,您 可能 通过至少检查对象 owned/passed 对被测 class 的某些预期调用确实发生来验证您的代码。然后你需要 verify()!
让我们假设您有一些 DAO class,它通过 JDBC 与数据库进行交互。您有一些方法可以将数据写入数据库并希望对其进行单元测试。为此,您可能会模拟 Connection
class。当您在数据库中写入时,您可能会在此 mock 上调用 commit
方法,但它的 return 类型是 void
,因此您不能保证在期间调用该方法你的测试。要解决此类问题,您可以使用 verify
。
希望对您有所帮助!
为了简化...假设您正在使用某些参数测试方法 A。方法A所做的就是调用方法B、C和D。
使用 Mockito.verify 你可以测试方法 B、C、D 是否真的被调用了。它甚至可以让您指定更复杂的测试,例如:
- 至少(1)
- 最多(10)
当您测试的方法根据您调用它时使用的参数表现不同时,它真的很有用。
方法return或者void
。
在单元测试中,作为一种方法 returns 东西,通常你想用一个特定的值模拟它的结果,并检查被测试方法的流程是否按预期进行。
就好像一个模拟returns 东西的方法一样有意义,通常你需要它的结果:在被测试方法的下一个语句中或者在被测试方法的结果return 中。
作为一种方法return什么都不是 (void
),情况有所不同:您不能模拟其结果。
但是您可以断言此方法已被调用并带有预期参数。
例如想象一个 PrinterService
class 来打印文档
public class PrintService{
...
public void printMessage(String message){
os.print(message);
}
}
并且假设您需要在另一个 class.
的单元测试期间隔离它
这里是测试方法:
public class PrintClient{
...
PrintService printService;
public void print(String message, PrinterParameters printerParameters...){
... // do some tasks
...
printService.print(message);
...
}
}
PrintService.print()
return没什么。
所以在 PrintClient
的单元测试中,你不想模拟 PrintService.print()
的结果,因为它没有。
你只想检查它是用传递给的 message
参数调用的
PrintClient
测试方法。
@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);
...
}
}