本文是我们名为“ 用Mockito进行测试 ”的学院课程的一部分。
在本课程中,您将深入了解Mockito的魔力。 您将了解有关“模拟”,“间谍”和“部分模拟”的信息,以及它们相应的Stubbing行为。 您还将看到使用测试双打和对象匹配器进行验证的过程。 最后,讨论了使用Mockito的测试驱动开发(TDD),以了解该库如何适合TDD的概念。 在这里查看 !
目录
1.什么是验证?
验证是确认模拟行为的过程。 这对于确定我们正在测试的类是否已按预期方式与其任何依赖项进行交互非常有用。 有时我们对从Mock返回的值不感兴趣,但是对被测类如何与之交互,发送什么值或调用它的频率感兴趣。 确认此行为的过程是验证,Mockito提供了许多工具来允许我们执行此操作。
2.使用verify()
Mockito工具箱中用于执行验证的主要工具是org.mockito.Mockito.verify()
方法。 verify方法将Mock对象作为参数,并返回与Mock相同的Class的实例,从而允许您调用Class的方法,Mockito将该类的方法解释为验证该方法是否存在某种交互的请求。
让我们再次看一下上一教程中的打印机界面。
public interface Printer {
void printTestPage();
}
我们可以创建一个简单的单元测试来演示使用模拟打印机进行验证
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class PrinterTest {
@Mock
private Printer printer;
@Test
public void simple_interaction_verification() {
// Given
// When
printer.printTestPage();
// Then
verify(printer).printTestPage();
}
}
我们可以看到我们的单元测试首先调用printer.printTestPage()
。 这是在模拟被测类中的可能交互,但是为了简单起见,我们在单元测试类中进行了模拟。 下一个调用是对verify(printer).printTestPage()
的调用。 这指示Mockito检查是否对Mock打印机的printTestPage()
方法进行了一次调用。
请仔细注意调用的语法, verify()
的参数是Mock对象,而不是方法调用。 如果我们放置了verify(printer.printTestPage())
我们将产生一个编译错误。 将其与存根中给定的/当语法相比较,语法形式为when(mockObject.someMethod()).thenReturn(...)
。
如果我们没有在此调用上方调用printTestPage()
来验证Mockito会产生验证错误,则通知我们没有调用printTestPage()
,如下所示:
Wanted but not invoked:
printer.printTestPage();
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification(PrinterTest.java:24)
Actually, there were zero interactions with this mock.
另外,如果我们再次调用printTestPage()
Mockito会产生一个验证错误,通知我们printTestPage()
调用过多。 该错误如下所示:
org.mockito.exceptions.verification.TooManyActualInvocations:
printer.printTestPage();
Wanted 1 time:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification(PrinterTest.java:25)
But was 2 times. Undesired invocation:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification(PrinterTest.java:22)
有用的是,错误告诉我们哪一行代码包含了多余的调用,在本例中为PrinterTest.java
第22行。
但是,如果我们想与我们的Mock进行多次互动,该怎么办? Mockito支持吗? 毫不奇怪,答案是肯定的!
verify()
方法采用第二个类型为org.mockito.verification.VerificationMode
参数,该参数可用于提供有关与模拟的所需交互的其他详细信息。
使用内置的验证模式
像往常一样,Mockito在org.mockito.Mockito中提供了许多方便的静态方法来创建VerificationModes,例如:
times(int)
这将验证该方法被调用次数。
@Test
public void simple_interaction_verification_times_1() {
// Given
// When
printer.printTestPage();
// Then
verify(printer, times(1)).printTestPage();
}
请注意, verify(mock)
是verify(mock, times(1))
的别名。
当然,我们可以使用times()
验证多个交互
@Test
public void simple_interaction_verification_times_3() {
// Given
// When
printer.printTestPage();
printer.printTestPage();
printer.printTestPage();
// Then
verify(printer, times(3)).printTestPage();
}
当实际的调用次数与预期的次数不匹配时,此VerificationMode
将产生有用的错误。
调用不足:
org.mockito.exceptions.verification.TooLittleActualInvocations:
printer.printTestPage();
Wanted 3 times:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification_times_3(PrinterTest.java:49)
But was 2 times:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification_times_3(PrinterTest.java:45)
调用过多:
org.mockito.exceptions.verification.TooManyActualInvocations:
printer.printTestPage();
Wanted 3 times:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification_times_3(PrinterTest.java:50)
But was 4 times. Undesired invocation:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simple_interaction_verification_times_3(PrinterTest.java:47)
atLeastOnce()
, atLeast(int)
这将验证该方法至少被调用了给定的次数。
@Test
public void simple_interaction_verification_atleastonce() {
// Given
// When
printer.printTestPage();
printer.printTestPage();
// Then
verify(printer, atLeastOnce()).printTestPage();
}
@Test
public void simple_interaction_verification_atleast_2() {
// Given
// When
printer.printTestPage();
printer.printTestPage();
printer.printTestPage();
// Then
verify(printer, atLeast(2)).printTestPage();
}
像往常一样,我们得到全面的错误报告:
org.mockito.exceptions.verification.TooLittleActualInvocations:
printer.printTestPage();
Wanted *at least* 2 times:
-> at com.javacodegeeks.hughwphamill.mockito.stubbing.PrinterTest.simpl