类Mockito
- java.lang.Object继承
-
- org.mockito.ArgumentMatchers
-
- org.mockito.Mockito
-
-
直接已知子类:
- BDDMockito
公共类Mockito 扩展了ArgumentMatchers
Mockito图书馆可以模拟创建,验证和存根。这个javadoc内容也可以在http://mockito.org的网页上找到。所有的文档都保存在javadoc中,因为它保证了网页内容与源代码内容的一致性。即使脱机工作,它也允许直接从IDE访问文档。它激励Mockito开发人员随时随地记录他们编写的代码,每天都提交。
内容
0.迁移到Mockito 2
0.1 Mockito Android支持
0.2免配置内联模拟
1.让我们来验证一些行为!
来自“简明英汉词典”有些残肢呢
3.参数匹配器
4.验证确切的调用次数/至少一次/从不
5.使用异常来替代void方法
6.按顺序验证
7.确保模拟中从未发生过交互
8.查找多余的调用
9.速记mocks创建 -@Mock
注释
10.连续调用连续调用(迭代器式stubbing)
11.带回调的stubbing
12.doReturn()
|doThrow()
|doAnswer()
|doNothing()
|doCallRealMethod()
方法家族
13.
监视真实对象14.更改未打开的调用的默认返回值(从1.7开始)
15.捕获进一步断言的参数(从1.8.0开始)
16.实际部分模拟(从1.8.0开始)
17.重置模拟(自1.8 0.0)
18.故障处理及验证框架使用(由于1.8.0)
19.别名为行为驱动开发(由于1.8.0)
20串行化嘲笑(由于1.8.1)
21.新的注释:@Captor
,@Spy
,@InjectMocks
(由于1.8。 3)
22.验证与超时(由于1.8.5)
23的自动实例化@Spies
,@InjectMocks
并构造注射善(由于1.9.0)
24.一衬垫存根(由于1.9.0)
25.验证忽略存根(从1.9.0开始)
26.嘲弄细节(在2.2.x中得到改进)
27.委托实际实例的调用(从1.9.5开始)
28.MockMaker
API(从1.9.5开始)
29. BDD风格验证自1.10.0)
30.间谍或嘲笑抽象类(从2011年10月1日,在2.7.13和2.7.14进一步增强)
31. Mockito嘲笑可以在类加载器(从1.10.0)开始序列化 / 反序列化
32.更好的通用(从1.10.0开始)
33. Mockito JUnit规则(从1.10.17开始)
34. 打开或关闭插件(从1.10.15开始)
35.自定义验证失败消息(从2.1.0开始)
36. Java 8 Lambda Matcher支持(自2.1.0起)
37. Java 8自定义答案支持(自2.1.0起)
38.元数据和通用类型保留(自2.1.0起)
39.嘲笑最终类型,枚举和最终方法(从2.1.0开始)
40.(* new *)提高生产力和清理测试,使用更严格的Mockito(自2. +开始)
41.(** new **)用于框架集成的高级公共API(自2.10。+起)
42.(** new **)用于集成的新API:收听验证开始事件(自2.11。+起)
0. 迁移到Mockito 2
为了继续改进Mockito,进一步提高单元测试的体验,我们希望你升级到2.1.0!Mockito遵循 语义版本控制 ,仅在主要版本升级时才包含重大更改。在图书馆的生命周期中,突破变化是推出一系列改变现有行为甚至更改API的全新功能所必需的。有关新版本的综合指南,包括不兼容的更改,请参阅“ Mockito 2的新功能 ”wiki页面。我们希望你喜欢Mockito 2!0.1。Mockito Android支持
随着Mockito版本2.6.1我们运送“原生”Android支持。要启用Android支持,请将`mockito-android`库作为依赖项添加到您的项目中。这个工件被发布到同一个Mockito组织,可以导入为Android如下:
您可以继续在常规虚拟机上运行相同的单元测试,在上面显示的“testCompile”范围内使用“mockito-core”工件。请注意,由于Android VM的限制,您无法使用Android上的 内联模拟器 。如果您在Android上遇到模拟问题,请 在官方问题跟踪器上 打开一个问题 。请提供您正在使用的Android版本和项目的相关性。repositories { jcenter() } dependencies { testCompile "org.mockito:mockito-core:+" androidTestCompile "org.mockito:mockito-android:+" }
0.2。免配置内联模拟
从版本2.7.6开始,我们提供了“mockito-inline”工件,可以 在 不配置MockMaker扩展文件的情况下进行 内联模拟。要使用这个,添加`mockito-inline`而不是`mockito-core`神器,如下所示:
请注意,当内联模拟功能被集成到默认模拟器中时,这个工件可能会被废除。repositories { jcenter() } dependencies { testCompile "org.mockito:mockito-inline:+" }
有关内联模拟的更多信息,请参阅第39节。
1. 让我们验证一些行为!
下面的例子嘲笑一个List,因为大多数人都熟悉的界面(如add()
,get()
,clear()
方法)。
实际上,请不要模拟List类。改用真实的实例。//Let's import Mockito statically so that the code looks clearer import static org.mockito.Mockito.*; //mock creation List mockedList = mock(List.class); //using mock object mockedList.add("one"); mockedList.clear(); //verification verify(mockedList).add("one"); verify(mockedList).clear();
一旦创建,模拟将记住所有的交互。然后,您可以选择性地验证您感兴趣的任何互动。
来自“简明英汉词典”有些残肢呢
//You can mock concrete classes, not just interfaces LinkedList mockedList = mock(LinkedList.class); //stubbing when(mockedList.get(0)).thenReturn("first"); when(mockedList.get(1)).thenThrow(new RuntimeException()); //following prints "first" System.out.println(mockedList.get(0)); //following throws runtime exception System.out.println(mockedList.get(1)); //following prints "null" because get(999) was not stubbed System.out.println(mockedList.get(999)); //Although it is possible to verify a stubbed invocation, usually it's just redundant //If your code cares what get(0) returns, then something else breaks (often even before verify() gets executed). //If your code doesn't care what get(0) returns, then it should not be stubbed. Not convinced? See here. verify(mockedList).get(0);
- 默认情况下,对于返回值的所有方法,mock将根据需要返回null,原始/原始包装器值或空集合。例如,对于int / Integer为0,对于布尔值/布尔值为false。
- 可以覆盖桩号:例如,普通桩可以进入夹具设置,但测试方法可以覆盖它。请注意,覆盖残片是一种潜在的代码异味,指出了太多的残片
- 一旦存留,该方法总是会返回一个存根值,而不管它被调用多少次。
- 最后的茬更重要 - 当你多次用相同的参数扼杀相同的方法。换句话说:存根的顺序很重要,但它只是很少有意义的,例如当存根完全相同的方法调用时,或者有时在使用参数匹配器时等等。
3. 参数匹配器
Mockito以自然的java风格验证参数值:使用equals()
方法。有时,当需要额外的灵活性时,你可以使用参数匹配器://stubbing using built-in anyInt() argument matcher when(mockedList.get(anyInt())).thenReturn("element"); //stubbing using custom matcher (let's say isValid() returns your own matcher implementation): when(mockedList.contains(argThat(isValid()))).thenReturn("element"); //following prints "element" System.out.println(mockedList.get(999)); //you can also verify using an argument matcher verify(mockedList).get(anyInt()); //argument matchers can also be written as Java 8 Lambdas verify(mockedList).add(argThat(someString -> someString.length() > 5));
参数匹配允许灵活的验证或存根。 查看更多内置匹配器和自定义参数匹配器/ hamcrest匹配器的示例。
Click here
or here
有关自定义参数匹配器的信息,请查看javadoc的
ArgumentMatcher
类。使用复杂的参数匹配是合理的。
equals()
与偶尔anyX()
匹配使用的自然匹配风格倾向于给干净和简单的测试。有时候重构代码以允许equals()
匹配甚至实现equals()
方法来帮助进行测试会更好。另外,阅读第15节或javadoc的
ArgumentCaptor
类。ArgumentCaptor
是参数匹配器的一个特殊的实现,捕获进一步的断言的参数值。参数匹配器警告:
如果使用参数匹配器,所有参数都必须由匹配器提供。
以下示例显示验证,但同样适用于存根:
verify(mock).someMethod(anyInt(), anyString(), eq("third argument")); //above is correct - eq() is also an argument matcher verify(mock).someMethod(anyInt(), anyString(), "third argument"); //above is incorrect - exception will be thrown because third argument is given without an argument matcher.
匹配方法
anyObject()
,eq()
不要返回匹配器。在内部,他们在堆栈上记录匹配器并返回一个虚拟值(通常为空)。这个实现是由于Java编译器强加的静态类型的安全性。其后果是,你不能使用anyObject()
,eq()
验证/存根方法之外的方法。4. 验证调用的确切数量 / 至少x /从不
//using mock mockedList.add("once"); mockedList.add("twice"); mockedList.add("twice"); mockedList.add("three times"); mockedList.add("three times"); mockedList.add("three times"); //following two verifications work exactly the same - times(1) is used by default verify(mockedList).add("once"); verify(mockedList, times(1)).add("once"); //exact number of invocations verification verify(mockedList, times(2)).add("twice"); verify(mockedList, times(3)).add("three times"); //verification using never(). never() is an alias to times(0) verify(mockedList, never()).add("never happened"); //verification using atLeast()/atMost() verify(mockedList, atLeastOnce()).add("three times"); verify(mockedList, atLeast(2)).add("three times"); verify(mockedList, atMost(5)).add("three times");
次(1)是默认值。因此明确地使用时间(1)可以省略。
5. 使用异常来删除void方法
阅读更多关于doThrow(new RuntimeException()).when(mockedList).clear(); //following throws RuntimeException: mockedList.clear();
doThrow()
|doAnswer()
家庭在方法 第12 。6. 依次验证
按顺序进行验证是非常灵活的 - 您不必 逐个 验证所有交互,只 需要验证您有兴趣测试的 所有交互。// A. Single mock whose methods must be invoked in a particular order List singleMock = mock(List.class); //using a single mock singleMock.add("was added first"); singleMock.add("was added second"); //create an inOrder verifier for a single mock InOrder inOrder = inOrder(singleMock); //following will make sure that add is first called with "was added first, then with "was added second" inOrder.verify(singleMock).add("was added first"); inOrder.verify(singleMock).add("was added second"); // B. Multiple mocks that must be used in a particular order List firstMock = mock(List.class); List secondMock = mock(List.class); //using mocks firstMock.add("was called first"); secondMock.add("was called second"); //create inOrder object passing any mocks that need to be verified in order InOrder inOrder = inOrder(firstMock, secondMock); //following will make sure that firstMock was called before secondMock inOrder.verify(firstMock).add("was called first"); inOrder.verify(secondMock).add("was called second"); // Oh, and A + B can be mixed together at will
另外,您可以创建一个InOrder对象,仅传递与按序验证相关的模拟。
7. 确保模拟中从未发生过交互
//using mocks - only mockOne is interacted mockOne.add("one"); //ordinary verification verify(mockOne).add("one"); //verify that method was never called on a mock verify(mockOne, never()).add("two"); //verify that other mocks were not interacted verifyZeroInteractions(mockTwo, mockThree);
8. 找到多余的调用
一句 警告 :谁做了很多经典的一些用户,期望-运行-验证嘲讽倾向于使用//using mocks mockedList.add("one"); mockedList.add("two"); verify(mockedList).add("one"); //following verification will fail verifyNoMoreInteractions(mockedList);
verifyNoMoreInteractions()
非常频繁,甚至在每个测试方法。verifyNoMoreInteractions()
不建议在每个测试方法中使用。verifyNoMoreInteractions()
是交互测试工具包的一个方便的断言。只有在相关时才使用它。滥用它会导致 过度指定 , 不易维护的 测试。你可以 在这里 找到更多的阅读 。另请参阅
never()
- 它更加明确,并充分传达意图。9. 速记嘲笑创作-
@Mock
注释- 最小化重复的模拟创建代码。
- 使测试类更具可读性。
- 使验证错误易于阅读,因为字段名称 用于识别模拟。
重要! 这需要在基类或测试运行的某个地方:public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider; private ArticleManager manager;
你可以使用内置的runner:MockitoAnnotations.initMocks(testClass);
MockitoJUnitRunner
或者一个规则:MockitoRule
。在这里阅读更多:
MockitoAnnotations
10. 连续调用(迭代器式存根)
有时我们需要为同一个方法调用存根不同的返回值/异常。典型的用例可能是嘲讽迭代器。原始版本的Mockito没有这个功能来促进简单的嘲笑。例如,而不是迭代器可以使用Iterable
或只是集合。那些提供自然的方式(例如使用真正的收藏)。在极少数的情况下,连续调用可能是有用的,但是:
可选的,连续存根的较短版本:when(mock.someMethod("some arg")) .thenThrow(new RuntimeException()) .thenReturn("foo"); //First call: throws runtime exception: mock.someMethod("some arg"); //Second call: prints "foo" System.out.println(mock.someMethod("some arg")); //Any consecutive call: prints "foo" as well (last stubbing wins). System.out.println(mock.someMethod("some arg"));
警告 :如果不使用链接when(mock.someMethod("some arg")) .thenReturn("one", "two", "three");
.thenReturn()
调用,而是使用具有相同匹配器或参数的多个存根,则每个存根将覆盖前一个存根://All mock.someMethod("some arg") calls will return "two" when(mock.someMethod("some arg")) .thenReturn("one") when(mock.someMethod("some arg")) .thenReturn("two")
11. 与回调扼杀
允许使用通用Answer
接口存根。还有另一个有争议的特点,最初没有包含在Mockito中。我们建议您简单地使用stubbing,
thenReturn()
或者thenThrow()
应该足以测试/测试任何干净简单的代码。但是,如果您确实需要使用通用的Answer接口进行存根,请使用下面的示例:when(mock.someMethod(anyString())).thenAnswer(new Answer() { Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); Object mock = invocation.getMock(); return "called with arguments: " + args; } }); //the following prints "called with arguments: foo" System.out.println(mock.someMethod("foo"));
12.
Stubbing void方法需要一个不同的方法,doReturn()
|doThrow()
|doAnswer()
|doNothing()
|doCallRealMethod()
方法家族when(Object)
因为编译器不喜欢方括号内的void方法。使用
doThrow()
时要与存根异常的无效方法:doThrow(new RuntimeException()).when(mockedList).clear(); //following throws RuntimeException: mockedList.clear();
您可以使用
doThrow()
,doAnswer()
,doNothing()
,doReturn()
和doCallRealMethod()
在地方与调用相应的when()
,对于任何方法。这是必要的,当你- 存根无效的方法
- 间谍对象的存根方法(见下文)
- 不止一次地存根相同的方法,在测试过程中改变模拟的行为。
when()
所有您的存根呼叫。阅读更多关于这些方法:
doReturn(Object)
doThrow(Throwable...)
doThrow(Class)
doAnswer(Answer)
doNothing()
doCallRealMethod()
13. 窥探真实的物体
你可以创建真实对象的间谍。当你使用间谍,那么 真正的 方法被调用(除非方法被扼杀)。真正的间谍应该谨慎地偶尔使用,例如在处理遗留代码时。
对真实物体的窥视可能与“部分嘲讽”概念有关。 在释放1.8之前,Mockito间谍不是真正的部分嘲讽。原因是我们认为部分模拟是一种代码味道。在某些时候,我们发现了部分模拟的合法用例(第三方接口,对遗留代码进行中间重构,整篇文章就 在这里)
List list = new LinkedList(); List spy = spy(list); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls *real* methods spy.add("one"); spy.add("two"); //prints "one" - the first element of a list System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed System.out.println(spy.size()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two");
关于间谍真相的重要窍门!
- 有时使用
when(Object)
吝啬的间谍是不可能或不切实际的。因此,当使用间谍时,请考虑doReturn
|Answer
|Throw()
存根方法的家庭。例:List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);
- Mockito *不会将调用委托给传入的实例,而是实际创建一个副本。所以如果你保留真实的实例并与之交互,不要期望被侦察者知道这些交互以及它们对实际实例状态的影响。其必然结果是,当* unstubbed *方法被调用*在间谍*,但*不上真正的实例*,你不会看到真正的实例的任何影响。
- 留意最后的方法。Mockito不会嘲笑最后的方法,所以底线是:当你窥探真实的物体时,你试图存根最后的方法=麻烦。你也将无法验证这些方法。
14.更改未发布的调用的默认返回值(从1.7开始)
您可以使用指定的策略为其返回值创建一个模拟。这是一个相当先进的功能,通常你不需要它来写出体面的测试。但是,使用 遗留系统 可能会有帮助。这是默认的答案,所以只有当你不存在方法调用时才会使用它。
Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS); Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
阅读更多关于这个有趣的答案的答案:
RETURNS_SMART_NULLS
15. 捕捉参数用于进一步断言(由于1.8.0)
Mockito以自然的java风格验证参数值:使用equals()
方法。这也是推荐的参数匹配方式,因为它使测试变得简单明了。但是,在某些情况下,在实际验证之后对某些论点作出断言是有帮助的。例如:
警告: 建议使用ArgumentCaptor进行验证, 但不要 使用stubbing。使用带有stub的ArgumentCaptor可能会降低测试可读性,因为在assert(也就是验证或'then')块之外创建了捕获器。也可以减少缺陷定位,因为如果不调用stubbed方法,则不会捕获任何参数。ArgumentCaptor
argument = ArgumentCaptor.forClass(Person.class); verify(mock).doSomething(argument.capture()); assertEquals("John", argument.getValue().getName()); ArgumentCaptor与自定义参数匹配器相关(请参阅
ArgumentMatcher
类javadoc )。这两种技术都可以用来确定传递给mock的某些参数。不过,ArgumentCaptor可能更适合以下情况:- 自定义参数匹配器不可能被重用
- 你只需要它来断言参数值来完成验证
ArgumentMatcher
通常更适合于存根。16. 真正的部分模拟(自1.8.0)
最后,在邮件列表上进行了许多内部辩论和讨论后,部分模拟支持被添加到Mockito。以前我们把部分模拟视为代码味道。但是,我们发现了部分模拟的合法用例 - 更多阅读: 这里在发布之前,1.8版本
spy()
并没有产生真正的部分嘲讽,这让一些用户感到困惑。阅读更多关于间谍:在这里或在javadoc的spy(Object)
方法。
像往常一样,您将阅读 部分模拟警告 :面向对象的编程通过将复杂性划分为单独的,特定的SRPy对象来解决更复杂的问题。部分模拟如何适应这种模式?那么,它只是不...部分模拟通常意味着复杂性已被移动到同一个对象上的不同方法。在大多数情况下,这不是您想要设计应用程序的方式。//you can create partial mock with spy() method: List list = spy(new LinkedList()); //you can enable partial mock capabilities selectively on mocks: Foo mock = mock(Foo.class); //Be sure the real implementation is 'safe'. //If real implementation throws exceptions or depends on specific state of the object then you're in trouble. when(mock.someMethod()).thenCallRealMethod();
但是,有些情况下,部分模拟会变得很方便:处理不能轻易更改的代码(第三方接口,传统代码的临时重构等)。但是,我不会使用部分模拟来实现新的,测试驱动的,设计的代码。
17. 重新模拟(从1.8.0开始)
智能Mockito用户很难使用这个功能,因为他们知道这可能是一个糟糕的测试的迹象。通常情况下,你不需要重置你的模拟,只是为每个测试方法创建新的模拟。不要
reset()
考虑写一些简单,小而重点明确的测试方法,而不要考虑冗长的,过度规定的测试。 第一个潜在的代码气味正reset()
处于测试方法的中间。这可能意味着你测试太多了。按照你的测试方法的低语:“请保持我们的小而专注于单一的行为”。在mockito邮件列表上有几个线程。我们添加
reset()
方法的唯一原因是使用容器注入的模拟工作成为可能。有关更多信息,请参阅FAQ(此处)。不要伤害你自己
reset()
在测试方法的中间是一个代码气味(你可能测试太多)。List mock = mock(List.class); when(mock.size()).thenReturn(10); mock.add(1); reset(mock); //at this point the mock forgot any interactions & stubbing
18. 故障排除和验证框架使用(从1.8.0开始)
首先,如果遇到任何问题,我建议您阅读Mockito FAQ: https: //github.com/mockito/mockito/wiki/FAQ如有疑问,您也可以发送到mockito邮件列表:http: //groups.google.com/group/mockito
接下来,您应该知道Mockito会验证您是否始终正确使用它。但是,有一个问题,所以请阅读javadoc
validateMockitoUsage()
19. 行为驱动开发的别名(自1.8.0开始)
行为驱动写作测试的开发风格使用/ / 给/ / / /然后 评论作为您的测试方法的基本部分。这正是我们如何编写测试的结果,我们热烈鼓励您这样做!在这里开始了解BDD:http://en.wikipedia.org/wiki/Behavior_Driven_Development
问题是当前stubbing api与正则表达式的时候,如果没有很好地集成//给定// // //然后评论。这是因为stubbing属于测试的给定组件,而不属于测试的when组件。因此,
BDDMockito
类引入了一个别名,以便您用BDDMockito.given(Object)
方法存根方法调用。现在它与BDD风格测试的特定组件非常好地整合!以下是测试的样子:
import static org.mockito.BDDMockito.*; Seller seller = mock(Seller.class); Shop shop = new Shop(seller); public void shouldBuyBread() throws Exception { //given given(seller.askForBread()).willReturn(new Bread()); //when Goods goods = shop.buyBread(); //then assertThat(goods, containBread()); }
20.可串行化的模拟(自1.8.1开始)
嘲笑可以被序列化。有了这个特性,你可以在需要依赖的地方使用模拟器来进行序列化。警告:这应该很少用于单元测试。
该行为是针对具有不可靠外部依赖性的BDD规范的特定用例实现的。这是在Web环境中,来自外部依赖项的对象正在被序列化以在层之间传递。
要创建可串行化的模拟使用
MockSettings.serializable()
:List serializableMock = mock(List.class, withSettings().serializable());
模拟可以被序列化,假设所有正常的 序列化要求都得到了这个类的满足。
因为间谍(...)方法没有一个接受MockSettings的重载版本,所以制作一个真正的对象间谍序列化是一个更多的努力。不用担心,你几乎不会使用它。
List
21.新的注释:
@Captor
,@Spy
,@InjectMocks
(由于1.8.3)版本1.8.3带来新的注释,有时可能会有所帮助:
- @
Captor
简化了创建ArgumentCaptor
- 当捕获的参数是一个令人讨厌的泛型类,并且您希望避免编译器警告时,它非常有用 - @
Spy
- 你可以用它来代替spy(Object)
。 - @
InjectMocks
- 将模拟或间谍字段自动注入到测试对象中。
请注意@
InjectMocks
也可以和@Spy
注解结合使用,这意味着Mockito会将mock注入到被测试的部分模拟中。这种复杂性是你仅仅使用部分模拟作为最后手段的另一个很好的理由。关于部分嘲讽,请参阅第16点。所有新的注释*仅*处理
MockitoAnnotations.initMocks(Object)
。就像为@Mock
注释您可以使用内置的亚军:MockitoJUnitRunner
或规则:MockitoRule
。22. 超时验证(自1.8.5开始)
允许超时验证。它会导致验证等待指定的时间段进行期望的交互,而不是立即失败,如果还没有发生。可能对并发条件下的测试有用。
这个功能应该很少使用 - 找出测试你的多线程系统的更好方法。
尚未实施以使用InOrder验证。
例子:
//passes when someMethod() is called within given time span verify(mock, timeout(100)).someMethod(); //above is an alias to: verify(mock, timeout(100).times(1)).someMethod(); //passes when someMethod() is called *exactly* 2 times within given time span verify(mock, timeout(100).times(2)).someMethod(); //passes when someMethod() is called *at least* 2 times within given time span verify(mock, timeout(100).atLeast(2)).someMethod(); //verifies someMethod() within given time span using given verification mode //useful only if you have your own custom verification modes. verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
23. 自动实例化
@Spies
,@InjectMocks
并构造注射善(由于1.9.0)Mockito现在将尝试实例化@
Spy
并InjectMocks
使用构造函数注入,setter注入或字段注入来实例化@ 字段。要利用此功能,您需要使用的优势
MockitoAnnotations.initMocks(Object)
,MockitoJUnitRunner
或MockitoRule
。阅读更多关于可用的技巧和javadoc中的注入规则
InjectMocks
//instead: @Spy BeerDrinker drinker = new BeerDrinker(); //you can write: @Spy BeerDrinker drinker; //same applies to @InjectMocks annotation: @InjectMocks LocalPub;
24. 单线存根(自1.9.0开始)
Mockito现在可以让你创建嘲讽时。基本上,它允许在一行代码中创建一个存根。这可以有助于保持测试代码的清洁。例如,一个无聊的存根可以在测试中的字段初始化时创建和存根:
public class CarTest { Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock(); @Test public void should... {}
25. 验证忽略存根(从1.9.0开始)
为了验证,Mockito现在允许忽略存根。有时加上
verifyNoMoreInteractions()
或验证时有用inOrder()
。有助于避免冗余验证,通常我们对验证存根不感兴趣。警告,
ignoreStubs()
可能导致过度使用verifyNoMoreInteractions(ignoreStubs(...)); 请记住,Mockito不建议轰炸每个测试与verifyNoMoreInteractions()
javadoc概述的原因verifyNoMoreInteractions(Object...)
一些例子:
verify(mock).foo(); verify(mockTwo).bar(); //ignores all stubbed methods: verifyNoMoreInteractions(ignoreStubs(mock, mockTwo)); //creates InOrder that will ignore stubbed InOrder inOrder = inOrder(ignoreStubs(mock, mockTwo)); inOrder.verify(mock).foo(); inOrder.verify(mockTwo).bar(); inOrder.verifyNoMoreInteractions();
高级的例子和更多的细节可以在javadoc中找到
ignoreStubs(Object...)
26. 嘲弄细节(在2.2.x中改进)
Mockito提供API来检查模拟对象的细节。这个API对高级用户和模拟框架集成商很有用。
欲了解更多信息,请参阅javadoc//To identify whether a particular object is a mock or a spy: Mockito.mockingDetails(someObject).isMock(); Mockito.mockingDetails(someObject).isSpy(); //Getting details like type to mock or default answer: MockingDetails details = mockingDetails(mock); details.getMockCreationSettings().getTypeToMock(); details.getMockCreationSettings().getDefaultAnswer(); //Getting interactions and stubbings of the mock: MockingDetails details = mockingDetails(mock); details.getInteractions(); details.getStubbings(); //Printing all interactions (including stubbing, unused stubs) System.out.println(mockingDetails(mock).printInvocations());
MockingDetails
。27. 委托实际实例(从1.9.5开始)
对于使用通常的间谍API 很难嘲笑或间谍的对象的间谍或部分嘲笑是有用的。自从Mockito 1.10.11之后,代表可能会或可能不会与模拟类型相同。如果类型不同,则需要在委托类型上找到匹配的方法,否则抛出异常。这个功能的可能用例:
- 最后的课程,但有一个接口
- 已经自定义代理对象
- 使用finalize方法的特殊对象,即避免执行2次
与普通间谍的区别:
- 常规spy(
spy(Object)
)包含spied实例的所有状态,并且在spy上调用方法。侦察实例只用于模拟创建从状态复制。如果你对一个普通间谍调用一个方法,并且在内部调用这个间谍的其他方法,那么这些调用就会被记住进行验证,并且可以被有效地删除。 - 委托的模拟只是将所有方法委托给委托。随着方法的委托,委托一直在使用。如果你调用了一个模拟的方法,委托它在内部调用其他方法,这些调用不会记住验证,存根也不会影响他们。委托模拟不如常规间谍那么强大,但是当不能创建常规间谍时,它是有用的。
在文档中查看更多信息
AdditionalAnswers.delegatesTo(Object)
。28.
MockMaker
API(自1.9.5以来)受谷歌Android家伙的要求和补丁的驱动,Mockito现在提供了一个扩展点,允许替换代理生成引擎。默认情况下,Mockito使用Byte Buddy 创建动态代理。
扩展点是为了扩展Mockito的高级用户。例如,现在可以使用针对的Mockito Android的测试与帮助dexmaker。
欲了解更多细节,动机和例子请参阅文档
MockMaker
。29. BDD风格验证(从1.10.0开始)
通过启动验证与BDD启用行为驱动开发(BDD)风格的验证 ,然后 关键字。
有关更多信息和示例,请参阅given(dog.bark()).willReturn(2); // when ... then(person).should(times(2)).ride(bike);
BDDMockito.then(Object)
}30. 侦察或嘲笑抽象类(自2011年10月1日起,在2.7.13和2.7.14中进一步加强)
现在可以方便地监视抽象类。请注意,过度使用间谍暗示代码设计的气味(见spy(Object)
)。以前,间谍只能在对象的实例上进行。新的API可以在创建模拟实例时使用构造函数。这对模拟抽象类特别有用,因为用户不再需要提供抽象类的实例。目前只支持无参数的构造函数,请告诉我们是否不够用。
欲了解更多信息,请参阅//convenience API, new overloaded spy() method: SomeAbstract spy = spy(SomeAbstract.class); //Mocking abstract methods, spying default methods of an interface (only available since 2.7.13) Function
function = spy(Function.class); //Robust API, via settings builder: OtherAbstract spy = mock(OtherAbstract.class, withSettings() .useConstructor().defaultAnswer(CALLS_REAL_METHODS)); //Mocking an abstract class with constructor arguments (only available since 2.7.14) SomeAbstract spy = mock(SomeAbstract.class, withSettings() .useConstructor("arg1", 123).defaultAnswer(CALLS_REAL_METHODS)); //Mocking a non-static inner abstract class: InnerAbstract spy = mock(InnerAbstract.class, withSettings() .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS)); MockSettings.useConstructor(Object...)
。31. Mockito嘲笑可以通过类加载器序列化 / 反序列化(从1.10.0开始)
Mockito在类加载器中引入序列化。与任何其他形式的序列化一样,模拟层次结构中的所有类型都必须可序列化,包含的答案。由于这种序列化模式需要相当多的工作,这是一个选择性的设置。
欲了解更多详情,请参阅// use regular serialization mock(Book.class, withSettings().serializable()); // use serialization across classloaders mock(Book.class, withSettings().serializable(ACROSS_CLASSLOADERS));
MockSettings.serializable(SerializableMode)
。32. 更好的通用支持与深存根(自1.10.0)
如果在课堂上可以获得一般信息,则深度桩技术已得到改进。这意味着类似这样的类可以使用而不必模拟行为。
请注意,在大多数情况下,模拟返回模拟是错误的。class Lines extends List<Line> { // ... } lines = mock(Lines.class, RETURNS_DEEP_STUBS); // Now Mockito understand this is not an Object but a Line Line line = lines.iterator().next();
33. Mockito JUnit规则(从1.10.17开始)
Mockito现在提供了一个JUnit规则。直到现在JUnit中有两种方法来初始化通过注释的Mockito如注释字段,,,等。@
Mock
@
Spy
@
InjectMocks
- 使用a注释JUnit测试类
@
RunWith
(MockitoJUnitRunner
.class) MockitoAnnotations.initMocks(Object)
在该方法中调用@
Before
更多信息请参阅@RunWith(YetAnotherRunner.class) public class TheTest { @Rule public MockitoRule mockito = MockitoJUnit.rule(); // ... }
MockitoJUnit.rule()
。34. 交换机上或关闭的插件(15年10月1日以来)
一个孵化功能使得mockito可以切换mockito插件。更多信息在这里PluginSwitch
。35. 自定义验证失败消息(从2.1.0开始)
如果验证失败,允许指定要打印的自定义消息。
例子:
// will print a custom message on verification failure verify(mock, description("This will print on failure")).someMethod(); // will work with any verification mode verify(mock, times(2).description("someMethod should be called twice")).someMethod();
36. Java 8 Lambda Matcher支持(从2.1.0开始)
您可以使用Java 8 lambda表达式
ArgumentMatcher
来减少依赖关系ArgumentCaptor
。如果您需要验证模拟函数调用的输入是否正确,那么您通常会使用ArgumentCaptor
找到使用的操作数,然后对其执行后续的断言。虽然对于复杂的例子这可能是有用的,它也是啰嗦。写一个lambda来表示匹配是相当容易的。当你的函数的参数和argThat结合使用的时候,它会作为一个强类型的对象传递给ArgumentMatcher,所以可以对它做任何事情。
例子:
// verify a list only had strings of a certain length added to it // note - this will only compile under Java 8 verify(list, times(2)).add(argThat(string -> string.length() < 5)); // Java 7 equivalent - not as neat verify(list, times(2)).add(argThat(new ArgumentMatcher(){ public boolean matches(String arg) { return arg.length() < 5; } })); // more complex Java 8 example - where you can specify complex verification behaviour functionally verify(target, times(1)).receiveComplexObject(argThat(obj -> obj.getSubObject().get(0).equals("expected"))); // this can also be used when defining the behaviour of a mock under different inputs // in this case if the input list was fewer than 3 items the mock returns null when(mock.someMethod(argThat(list -> list.size()<3))).willReturn(null);
37. Java 8自定义答案支持(从2.1.0开始)
由于
Answer
接口只有一个方法,所以已经可以在非常简单的情况下使用lambda表达式在Java 8中实现它。您需要使用方法调用的参数的次数越多,您需要更多地对参数进行类型转换InvocationOnMock
。例子:
为了方便起见,可以将使用方法调用参数的自定义答案/操作编写为Java 8 lambda表达式。即使在Java 7中,基于类型化界面的这些自定义答案也可以减少样板。特别是,这种方法将使测试使用回调函数更容易。方法// answer by returning 12 every time doAnswer(invocation -> 12).when(mock).doSomething(); // answer by using one of the parameters - converting into the right // type as your go - in this case, returning the length of the second string parameter // as the answer. This gets long-winded quickly, with casting of parameters. doAnswer(invocation -> ((String)invocation.getArgument(1)).length()) .when(mock).doSomething(anyString(), anyString(), anyString());
answer
和answerVoid
可用于创建答案。他们依赖于相关的答案接口,org.mockito.stubbing
最多支持5个参数。例子:
// Example interface to be mocked has a function like: void execute(String operand, Callback callback); // the example callback has a function and the class under test // will depend on the callback being invoked void receive(String item); // Java 8 - style 1 doAnswer(AdditionalAnswers.
answerVoid((operand, callback) -> callback.receive("dummy")) .when(mock).execute(anyString(), any(Callback.class)); // Java 8 - style 2 - assuming static import of AdditionalAnswers doAnswer(answerVoid((String operand, Callback callback) -> callback.receive("dummy")) .when(mock).execute(anyString(), any(Callback.class)); // Java 8 - style 3 - where mocking function to is a static member of test class private static void dummyCallbackImpl(String operation, Callback callback) { callback.receive("dummy"); } doAnswer(answerVoid(TestClass::dummyCallbackImpl) .when(mock).execute(anyString(), any(Callback.class)); // Java 7 doAnswer(answerVoid(new VoidAnswer2 () { public void answer(String operation, Callback callback) { callback.receive("dummy"); }})).when(mock).execute(anyString(), any(Callback.class)); // returning a value is possible with the answer() function // and the non-void version of the functional interfaces // so if the mock interface had a method like boolean isSameString(String input1, String input2); // this could be mocked // Java 8 doAnswer(AdditionalAnswers. answer((input1, input2) -> input1.equals(input2)))) .when(mock).execute(anyString(), anyString()); // Java 7 doAnswer(answer(new Answer2 () { public String answer(String input1, String input2) { return input1 + input2; }})).when(mock).execute(anyString(), anyString()); 38. 元数据和通用类型保留(从2.1.0开始)
Mockito现在保留对嘲笑的方法和类型以及通用元数据的注释。以前,模拟类型不保留对类型的注释,除非它们是显式继承的,并且永远不会在方法上保留注释。因此,现在下列条件成立:
@
MyAnnotation class Foo { List
bar() { ... } } Class> mockType = mock(Foo.class).getClass(); assert mockType.isAnnotationPresent(MyAnnotation.class); assert mockType.getDeclaredMethod("bar").getGenericReturnType() instanceof ParameterizedType; 当使用Java 8时,Mockito现在也保留了类型注释。这是默认行为,如果使用替代方法可能不会成立
MockMaker
。39. 嘲笑最终类型,枚举和最终方法(从2.1.0开始)
Mockito现在提供了一个模拟Incubating
最终类和方法的可选支持。这是一个奇妙的改进,证明了Mockito对于改善测试体验的永恒追求。我们的抱负是Mockito“最后的课程和方法”。以前他们被认为是 unmockable ,防止用户嘲笑。我们已经开始讨论如何使这个功能默认启用。目前,该功能仍然是可选的,因为我们等待来自社区的更多反馈。此功能默认关闭,因为它基于完全不同的嘲笑机制,需要来自社区的更多反馈。
这个替代的模拟器使用Java Instrumentation API和子类的组合,而不是创建一个新的类来表示一个模拟。这样,就可以模拟最终的类型和方法。
这个模拟器默认关闭,因为它是基于完全不同的嘲弄机制,需要来自社区的更多反馈。它可以通过mockito扩展机制显式激活,只需在类路径中创建一个
/mockito-extensions/org.mockito.plugins.MockMaker
包含该值的文件即可mock-maker-inline
。为了方便起见,Mockito团队在模拟器制造商预先配置的地方提供了一个神器。在您的项目中包含mockito-inline工件,而不是使用 mockito-core工件。请注意,一旦嘲笑最终的类和方法被整合到默认的模拟器中,这个工件可能会被终止。
关于这个模拟器的一些值得注意的笔记:
- 嘲笑最终的类型和枚举是不符合模拟设置,如:
- 明确的序列化支持
withSettings().serializable()
- 额外的接口
withSettings().extraInterfaces()
- 明确的序列化支持
- 有些方法不能被嘲弄
- 包的可见方法
java.*
native
方法
- 包的可见方法
- 这个模拟器是围绕Java代理运行时附件设计的; 这需要一个兼容的JVM,它是JDK(或Java 9 VM)的一部分。当在Java 9之前的非JDK虚拟机上运行时,可以 在启动JVM时使用参数手动添加Byte Buddy Java代理程序jar
-javaagent
。
如果你对这个功能的更多细节感兴趣,请阅读javadoc
org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
40. (*新*)提高生产力和清洁测试与“更严格”Mockito(自2 + +)
要快速了解“更严格”的Mockito如何使您的工作效率更高,并使测试更加清洁,请参阅:- 用JUnit规则严格存根 -
MockitoRule.strictness(Strictness)
与Strictness.STRICT_STUBS
- 与JUnit亚军严格扼杀 -
MockitoJUnitRunner.StrictStubs
- 严格存根,如果你不能使用亚军/规则(如TestNG) -
MockitoSession
- 不必要的残片检测
MockitoJUnitRunner
- 存根参数不匹配警告,记录在
MockitoHint
默认情况下,“松散”使得Mockito测试有时难以调试。在某些情况下,错误配置的桩(如使用错误的参数)会强制用户使用调试器运行测试。理想情况下,测试失败是显而易见的,不需要调试器来确定根本原因。从版本2.1开始,Mockito已经获得了将框架推向“严格”的新功能。我们希望Mockito能够提供出色的可调试性,同时不会失去其核心嘲笑风格,并针对直观性,清晰度和清晰的测试代码进行了优化。
帮助Mockito!尝试新功能,给我们反馈,参加GitHub 第769期关于Mockito严格性的讨论 。
41. (** **新)先进的架构整合公共API(自2.10。+)
在2017年夏季,我们决定Mockito 应该 为高级框架集成 提供更好的API 。新的API不适用于想要编写单元测试的用户。它旨在用于其他测试工具和模拟框架,需要扩展或包装Mockito一些自定义的逻辑。在设计和实施过程( 问题1110 )期间,我们已经开发并更改了以下公共API元素:- 新增功能
MockitoPlugins
- 使框架集成商可以访问默认的Mockito插件。当需要实现自定义插件(如MockMaker
将某些行为委托给默认的Mockito实现)时非常有用。 - 新建
MockSettings.build(Class)
- 创建Mockito稍后使用的模拟设置的不可变视图。用于创建调用InvocationFactory
或实现自定义时MockHandler
。 - 新建
MockingDetails.getMockHandler()
- 其他框架可以使用模拟处理程序以编程方式模拟模拟对象上的调用。 - 新建
MockHandler.getMockSettings()
- 有用的获取模拟对象创建的设置。 - 新建
InvocationFactory
- 提供创建Invocation
对象实例的方法。对于需要以编程方式模拟模拟对象的方法调用的框架集成非常有用。 - 新建
MockHandler.getInvocationContainer()
- 提供对没有方法的调用容器对象(标记接口)的访问。容器需要隐藏内部实现,并避免泄漏到公共API。 - 改变
Stubbing
- 它现在扩展Answer
接口。它是向后兼容的,因为存根接口不可扩展(请参阅NotExtensible
)。这个改变对我们的用户应该是无缝的。 - 弃用
InternalMockHandler
- 为了适应API的变化,我们需要弃用这个接口。界面总是被记录为内部的,我们没有证据表明它被社区使用。弃用应该完全无缝的为我们的用户。 NotExtensible
- 公共注释,指示用户不应该提供给定类型的自定义实现。帮助框架集成商和我们的用户了解如何安全地使用Mockito API。
42. (** new **)用于集成的新API:收听验证开始事件(自2.11。+起)
Spring Boot 等框架集成需要公共API来解决双代理用例( 问题1191 )。我们补充说:- 新建
VerificationStartedListener
并VerificationStartedEvent
启用框架集成器来替换模拟对象以进行验证。主要的驱动用例是Spring Boot集成。有关详细信息,请参阅JavadocVerificationStartedListener
。 - 新的公开方法
MockSettings.verificationStartedListeners(VerificationStartedListener...)
允许在模拟创建时提供验证开始的听众。 MockingDetails.getMock()
添加了新的方便的方法,使MockingDetails
API更完整。我们发现这个方法在实现过程中很有用。
-
-
字段摘要
修饰符和类型 字段和说明 static Answer
CALLS_REAL_METHODS
可选Answer
用于mock(Class, Answer)
static Answer
RETURNS_DEEP_STUBS
可选Answer
用于mock(Class, Answer)
。static Answer
RETURNS_DEFAULTS
Answer
每个模拟的默认值, 如果 模拟不被扼杀。static Answer
RETURNS_MOCKS
可选Answer
用于mock(Class, Answer)
static Answer
RETURNS_SELF
可选Answer
用于mock(Class, Answer)
。static Answer
RETURNS_SMART_NULLS
可选Answer
用于mock(Class, Answer)
。
-
构造器摘要
构造函数和说明 Mockito()
-
方法摘要
修饰符和类型 方法和描述 static VerificationAfterDelay
after(long millis)
允许在给定的时间内进行验证。static VerificationMode
atLeast(int minNumberOfInvocations)
允许至少x验证。static VerificationMode
atLeastOnce()
允许至少一次验证。static VerificationMode
atMost(int maxNumberOfInvocations)
允许进行最多x验证。static VerificationMode
calls(int wantedNumberOfInvocations)
按顺序进行非贪婪验证。static
void clearInvocations(T... mocks)
使用这个方法只是为了清除调用,当存根是非平凡的。static VerificationMode
description(String description)
如果验证失败,则添加要打印的说明。static Stubber
doAnswer(Answer answer)
使用doAnswer()
时要与存根通用空隙的方法Answer
。static Stubber
doCallRealMethod()
使用doCallRealMethod()
时要调用真正执行的方法。static Stubber
doNothing()
使用doNothing()
设置无效的方法什么也不做。static Stubber
doReturn(Object toBeReturned)
使用doReturn()
在那些极少数情况下,你不能使用when(Object)
。static Stubber
doReturn(Object toBeReturned, Object... toBeReturnedNext)
相同doReturn(Object)
但设置要返回的连续值。static Stubber
doThrow(Class extends Throwable> toBeThrown)
使用doThrow()
时要与存根异常的无效方法。static Stubber
doThrow(Class extends Throwable> toBeThrown, Class extends Throwable>... toBeThrownNext)
与doThrow(Class)
设置连续的异常类相同。static Stubber
doThrow(Throwable... toBeThrown)
使用doThrow()
时要与存根异常的无效方法。static MockitoFramework
framework()
对于高级用户或框架集成商。static Object[]
ignoreStubs(Object... mocks)
为了验证,忽略了给定模拟的残留方法。static InOrder
inOrder(Object... mocks)
创建InOrder
允许按顺序验证模拟的对象。static
T mock(Class
classToMock) 创建给定的类或接口的模拟对象。static
T mock(Class
classToMock, Answer defaultAnswer) 创建一个指定的策略模拟其交互的答案。static
T mock(Class
classToMock, MockSettings mockSettings) 用一些非标准设置创建一个模拟。static
T mock(Class
classToMock, String name) 指定模拟名称。static MockingDetails
mockingDetails(Object toInspect)
返回一个MockingDetails实例,该实例可以检查特定对象的Mockito相关信息。static MockitoSessionBuilder
mockitoSession()
MockitoSession
是一个可选的强烈推荐的功能,通过消除样板代码和添加额外的验证来帮助推动清洁测试。static VerificationMode
never()
别名times(0)
,看times(int)
static VerificationMode
only()
允许检查给定的方法是唯一被调用的方法。static
void reset(T... mocks)
智能Mockito用户很难使用这个功能,因为他们知道这可能是一个糟糕的测试的迹象。static
T spy(Class
classToSpy) 请参阅文档spy(Object)
。static
T spy(T object)
创建真实对象的间谍。static VerificationWithTimeout
timeout(long millis)
允许超时验证。static VerificationMode
times(int wantedNumberOfInvocations)
允许验证确切的调用次数。static void
validateMockitoUsage()
首先,如果遇到任何问题,我建议您阅读Mockito FAQ: https: //github.com/mockito/mockito/wiki/FAQstatic
T verify(T mock)
验证 一次发生的 某些行为。static
T verify(T mock, VerificationMode mode)
验证某些行为发生至少一次/确切的次数/从不。static void
verifyNoMoreInteractions(Object... mocks)
检查是否有任何给定的模拟有任何未经验证的交互。static void
verifyZeroInteractions(Object... mocks)
验证除了先前验证的交互之外,在给定的模拟上没有发生交互。
这种方法具有相同的行为verifyNoMoreInteractions(Object...)
。static
OngoingStubbing when(T methodCall)
启用存根方法。static MockSettings
withSettings()
允许使用附加的模拟设置进行模拟创建。-
从类org.mockito继承的方法 ArgumentMatchers
any, any, anyBoolean, anyByte, anyChar, anyCollection, anyCollectionOf, anyDouble, anyFloat, anyInt, anyIterable, anyIterableOf, anyList, anyListOf, anyLong, anyMap, anyMapOf, anyObject, anySet, anySetOf, anyShort, anyString, anyVararg, argThat, booleanThat, byteThat, charThat, contains, doubleThat, endsWith, eq, eq, eq, eq, eq, eq, eq, eq, eq, floatThat, intThat, isA, isNotNull, isNotNull, isNull, isNull, longThat, matches, matches, notNull, notNull, nullable, refEq, same, shortThat, startsWith
-
从类java.lang继承的方法 目的
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
-
-
-
字段细节
-
RETURNS_DEFAULTS
public static final Answer < Object > RETURNS_DEFAULTS
Answer
每个模拟的默认值, 如果 模拟不被扼杀。通常它只是返回一些空的值。Answer
可以用来定义未打开的调用的返回值。此实现首先尝试全局配置,如果没有全局配置,则将使用返回零,空集合,空值等的默认答案。
-
RETURNS_SMART_NULLS
public static final Answer: < Object > RETURNS_SMART_NULLS
可选Answer
用于mock(Class, Answer)
。Answer
可以用来定义未打开的调用的返回值。这个实现在处理遗留代码时会很有帮助。未被拼接的方法通常返回null。如果你的代码使用了一个未经调用的调用返回的对象,你将得到一个NullPointerException异常。Answer的这个实现返回SmartNull而不是null。
SmartNull
比NPE提供更好的异常消息,因为它指出了未调用方法被调用的行。你只需点击堆栈跟踪。ReturnsSmartNulls
首先尝试返回普通的值(零,空集合,空字符串等),然后尝试返回SmartNull。如果返回类型是final,则null
返回plain 。ReturnsSmartNulls
将可能是Mockito 3.0.0中的默认返回值策略例:
Foo mock = mock(Foo.class, RETURNS_SMART_NULLS); //calling unstubbed method here: Stuff stuff = mock.getStuff(); //using object returned by unstubbed call: stuff.doSomething(); //Above doesn't yield NullPointerException this time! //Instead, SmartNullPointerException is thrown. //Exception's cause links to unstubbed mock.getStuff() - just click on the stack trace.
-
RETURNS_MOCKS
public static final Answer: < Object > RETURNS_MOCKS
可选Answer
用于mock(Class, Answer)
Answer
可以用来定义未打开的调用的返回值。这个实现在处理遗留代码时会很有帮助。
ReturnsMocks首先尝试返回普通的值(零,空集合,空字符串等),然后尝试返回模拟。如果返回类型不能被模拟(例如final),则
null
返回plain 。
-
RETURNS_DEEP_STUBS
public static final Answer: < Object > RETURNS_DEEP_STUBS
可选Answer
用于mock(Class, Answer)
。显示深度存根工作原理的示例:
Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS); // note that we're stubbing a chain of methods here: getBar().getName() when(mock.getBar().getName()).thenReturn("deep"); // note that we're chaining method calls: getBar().getName() assertEquals("deep", mock.getBar().getName());
警告: 常规清洁代码很少需要此功能!将其留作遗留代码。嘲讽一个嘲讽返回一个模拟,返回一个模拟,(...),返回一些有意义的提示,违反得墨忒耳法或嘲弄价值对象(一个众所周知的反模式)。
我有一天在网上看到了很好的报价:每次模拟回来模拟一个仙女死亡。
请注意,这个答案将返回与存根相匹配的现有模拟。这种行为对于深存根是可以的,并且允许验证在链的最后模拟上工作。
when(mock.getBar(anyString()).getThingy().getName()).thenReturn("deep"); mock.getBar("candy bar").getThingy().getName(); assertSame(mock.getBar(anyString()).getThingy().getName(), mock.getBar(anyString()).getThingy().getName()); verify(mock.getBar("candy bar").getThingy()).getName(); verify(mock.getBar(anyString()).getThingy()).getName();
验证只适用于链中的最后一个模拟。您可以使用验证模式。
when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep"); when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep"); when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep"); person.getAddress("the docks").getStreet().getName(); person.getAddress("the docks").getStreet().getLongName(); person.getAddress("the docks").getStreet(Locale.ITALIAN).getName(); person.getAddress("the docks").getStreet(Locale.CHINESE).getName(); // note that we are actually referring to the very last mock in the stubbing chain. InOrder inOrder = inOrder( person.getAddress("the docks").getStreet(), person.getAddress("the docks").getStreet(Locale.CHINESE), person.getAddress("the docks").getStreet(Locale.ITALIAN) ); inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName(); inOrder.verify(person.getAddress("the docks").getStreet()).getLongName(); inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1)).getName(); inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();
多少深存根在内部工作?
//this: Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS); when(mock.getBar().getName(), "deep"); //is equivalent of Foo foo = mock(Foo.class); Bar bar = mock(Bar.class); when(foo.getBar()).thenReturn(bar); when(bar.getName()).thenReturn("deep");
当包含在链中的任何返回类型的方法不能被模拟时(例如:是原始类还是最终类),此功能将不起作用。这是因为java类型的系统。
-
CALLS_REAL_METHODS
public static final Answer < Object > CALLS_REAL_METHODS
可选Answer
用于mock(Class, Answer)
Answer
可以用来定义未打开的调用的返回值。这个实现在处理遗留代码时会很有帮助。当使用这个实现时,未解压的方法将委托给真正的实现。这是创建一个默认调用真实方法的部分模拟对象的一种方法。
像往常一样,您将阅读部分模拟警告:面向对象的编程通过将复杂性划分为单独的,特定的SRPy对象来解决更复杂的问题。部分模拟如何适应这种模式?那么,它只是不...部分模拟通常意味着复杂性已被移动到同一个对象上的不同方法。在大多数情况下,这不是您想要设计应用程序的方式。
但是,有些情况下,部分模拟会变得很方便:处理不能轻易更改的代码(第三方接口,传统代码的临时重构等)。但是,我不会使用部分模拟来实现新的,测试驱动的,设计的代码。
例:
Foo mock = mock(Foo.class, CALLS_REAL_METHODS); // this calls the real implementation of Foo.getSomething() value = mock.getSomething(); when(mock.getSomething()).thenReturn(fakeValue); // now fakeValue is returned value = mock.getSomething();
-
RETURNS_SELF
public static final Answer < Object > RETURNS_SELF
可选Answer
用于mock(Class, Answer)
。当一个方法被调用返回一个Type等于该类或一个超类的方法时,允许Builder mock返回自身。请记住,这个答案使用方法的返回类型。如果这个类型可以分配给模拟类,它将返回模拟。因此,如果你有一个方法返回一个超类(例如
考虑HttpRequesterWithHeaders中使用的HttpBuilder。Object
)它将匹配并返回模拟。
以下测试将成功public class HttpRequesterWithHeaders { private HttpBuilder builder; public HttpRequesterWithHeaders(HttpBuilder builder) { this.builder = builder; } public String request(String uri) { return builder.withUrl(uri) .withHeader("Content-type: application/json") .withHeader("Authorization: Bearer") .request(); } } private static class HttpBuilder { private String uri; private List
headers; public HttpBuilder() { this.headers = new ArrayList (); } public HttpBuilder withUrl(String uri) { this.uri = uri; return this; } public HttpBuilder withHeader(String header) { this.headers.add(header); return this; } public String request() { return uri + headers.toString(); } } @Test public void use_full_builder_with_terminating_method() { HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF); HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder); String response = "StatusCode: 200"; when(builder.request()).thenReturn(response); assertThat(requester.request("URI")).isEqualTo(response); }
-
-
构造函数的细节
-
的Mockito
公众Mockito()
-
-
方法细节
-
嘲笑
public static
T mock(Class classToMock) 创建给定的类或接口的模拟对象。见的例子中的javadoc
Mockito
类-
参数:
-
classToMock
- 类或接口来模拟
返回:
- 模拟对象
-
-
嘲笑
public static
T mock(Class classToMock, String name) 指定模拟名称。命名模拟可能对调试有帮助 - 名称用于所有验证错误。请注意,命名模拟不适用于使用太多模拟或协作者的复杂代码。 如果你有太多的mock,那么重构代码,这样很容易测试/调试,而不必命名模拟。
如果你使用
@Mock
注释,那么你已经免费命名模拟!@Mock
使用字段名称作为模拟名称。Read more.
见的例子中的javadoc
Mockito
类-
参数:
-
classToMock
- 类或接口来模拟 -
name
- 模拟
返回:
- 模拟对象
-
-
mockingDetails
公共静态 MockingDetails mockingDetails(Object toInspect)
返回一个MockingDetails实例,该实例可以检查特定对象的Mockito相关信息。可以用来找出给定的对象是否是Mockito模拟,或者找出给定的模拟是间谍还是模拟。在将来的Mockito版本中,MockingDetails可能会增长,并提供有关模拟的其他有用信息,例如调用,存根信息等。
-
参数:
-
toInspect
- - 检查对象。空输入是允许的。
返回:
-
一个
MockingDetails
实例。
以来:
- 1.9.5
-
-
嘲笑
public static
T mock(Class classToMock, Answer defaultAnswer) 创建一个指定的策略模拟其交互的答案。这是一个相当先进的功能,通常你不需要它来写出体面的测试。但是,使用旧系统时可能会有所帮助。这是默认的答案,所以只有当你不存在方法调用时才会使用它。
Foo mock = mock(Foo.class, RETURNS_SMART_NULLS); Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
见的例子中的javadoc
Mockito
类-
参数:
-
classToMock
- 类或接口来模拟 -
defaultAnswer
- 未打开的方法的默认答案
返回:
- 模拟对象
-
-
嘲笑
public static
T mock(Class classToMock, MockSettings mockSettings) 用一些非标准设置创建一个模拟。模拟的配置点数量增长,所以我们需要一个流利的方式来引入新的配置,而不会增加更多的重载Mockito.mock()方法。因此
MockSettings
。
小心使用,偶尔使用 。什么可能是你的测试需要非标准模拟的原因?被测试的代码是如此复杂以至于它需要非标准的模拟?你不喜欢重构测试中的代码,所以它是可测试的一个简单的方法?Listener mock = mock(Listener.class, withSettings() .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS)); );
也可以看看
withSettings()
见的例子中的javadoc
Mockito
类-
参数:
-
classToMock
- 类或接口来模拟 -
mockSettings
- 额外的模拟设置
返回:
- 模拟对象
-
-
间谍
公共静态
T间谍(T对象) 创建真实对象的间谍。间谍调用 真正的 方法,除非他们被扼杀。真正的间谍应该谨慎地偶尔使用,例如在处理遗留代码时。
像往常一样,您将阅读部分模拟警告:面向对象编程通过将复杂性划分为单独的,特定的SRPy对象来解决复杂性问题。部分模拟如何适应这种模式?那么,它只是不...部分模拟通常意味着复杂性已被移动到同一个对象上的不同方法。在大多数情况下,这不是您想要设计应用程序的方式。
但是,有些情况下,部分模拟会变得很方便:处理不能轻易更改的代码(第三方接口,传统代码的临时重构等)。但是,我不会使用部分模拟来实现新的,测试驱动的,设计的代码。
例:
List list = new LinkedList(); List spy = spy(list); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls real methods spy.add("one"); spy.add("two"); //prints "one" - the first element of a list System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed System.out.println(spy.size()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two");
关于间谍真相的重要窍门!
- 有时使用
when(Object)
吝啬的间谍是不可能或不切实际的。因此,对于间谍,建议始终使用doReturn
|Answer
|Throw()
|CallRealMethod
存根方法的家庭。例:List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);
- Mockito *不会将调用委托给传入的实例,而是实际创建一个副本。所以如果你保留真实的实例并与之交互,不要期望被侦察者知道这些交互以及它们对实际实例状态的影响。其必然结果是,当* unstubbed *方法被调用*在间谍*,但*不上真正的实例*,你不会看到真正的实例的任何影响。
- 留意最后的方法。Mockito不会嘲笑最后的方法,所以底线是:当你窥探真实的物体时,你试图存根最后的方法=麻烦。你也将无法验证这些方法。
见的例子中的javadoc
Mockito
类请注意,间谍不会有任何关于间谍类型的注释,因为CGLIB不会重写它们。对于依靠间谍来获得这些注释的代码来说,可能会很麻烦。
-
参数:
-
object
- 监视
返回:
- 一个真正的对象的间谍
- 有时使用
-
间谍
@Incubating public static
T spy(Class classToSpy) 请参阅文档spy(Object)
。滥用间谍暗示代码设计的气味。这个方法与原来的方法相反
spy(Object)
,是基于类而不是一个对象来创建一个间谍。有时候,基于类创建间谍更为方便,并避免提供一个间谍对象的实例。这对侦察抽象类非常有用,因为它们不能被实例化。另见MockSettings.useConstructor(Object...)
。例子:
SomeAbstract spy = spy(SomeAbstract.class); //Robust API, via settings builder: OtherAbstract spy = mock(OtherAbstract.class, withSettings() .useConstructor().defaultAnswer(CALLS_REAL_METHODS)); //Mocking a non-static inner abstract class: InnerAbstract spy = mock(InnerAbstract.class, withSettings() .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));
-
类型参数:
-
T
- 间谍的类型
参数:
-
classToSpy
- 要窥探的班级
返回:
- 提供的类的间谍 以来:
- 1.10.12
-
-
什么时候
public static
OngoingStubbing when(T methodCall) 启用存根方法。当你想要模拟特定的方法被调用时返回特定的值使用它。简单地说:“ 当 x方法被调用,然后返回y”。
例子:
有关throwables的void方法,请参见:when(mock.someMethod()).thenReturn(10); //you can use flexible argument matchers, e.g: when(mock.someMethod(anyString())).thenReturn(10); //setting exception to be thrown: when(mock.someMethod("some arg")).thenThrow(new RuntimeException()); //you can set different behavior for consecutive method calls. //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls. when(mock.someMethod("some arg")) .thenThrow(new RuntimeException()) .thenReturn("foo"); //Alternative, shorter version for consecutive stubbing: when(mock.someMethod("some arg")) .thenReturn("one", "two"); //is the same as: when(mock.someMethod("some arg")) .thenReturn("one") .thenReturn("two"); //shorter version for consecutive method calls throwing exceptions: when(mock.someMethod("some arg")) .thenThrow(new RuntimeException(), new NullPointerException();
doThrow(Throwable...)
可以覆盖桩号:例如,普通桩可以进入夹具设置,但测试方法可以覆盖它。请注意,覆盖残片是一种潜在的代码异味,指出了太多的残片。
一旦被存根,该方法将总是返回存根值,而不管被调用的次数多少。
最后的茬更重要 - 当你多次用相同的参数扼杀相同的方法。
尽管可以验证存根调用,但通常这只是多余的。比方说,你已经残废了
foo.bar()
。如果你的代码关心什么foo.bar()
返回,那么别的东西就会中断(通常在verify()
执行之前)。如果你的代码不在乎什么get(0)
返回,那么它不应该被扼杀。不服气?看到这里。见的例子中的javadoc
Mockito
类-
参数:
-
methodCall
- 方法被扼杀
返回:
- OngoingStubbing对象用于流利地存根。 不要 创建对此返回对象的引用。
-
-
校验
public static
T verify(T mock) 验证 一次发生的 某些行为。别名
verify(mock, times(1))
如:
以上相当于:verify(mock).someMethod("some arg");
verify(mock, times(1)).someMethod("some arg");
使用
equals()
方法比较传递的参数。阅读ArgumentCaptor
或ArgumentMatcher
找出其他方式匹配/断言传递的参数。尽管可以验证存根调用,但通常这只是多余的。比方说,你已经残废了
foo.bar()
。如果你的代码关心什么foo.bar()
返回,那么别的东西就会中断(通常在verify()
执行之前)。如果你的代码不在乎什么get(0)
返回,那么它不应该被扼杀。不服气?看到这里。见的例子中的javadoc
Mockito
类-
参数:
-
mock
- 待验证
返回:
- 模拟对象本身
-
-
校验
public static
T验证(T模拟, VerificationMode 模式) 验证某些行为发生至少一次/确切的次数/从不。例如:
次(1)是默认值 ,可以省略verify(mock, times(5)).someMethod("was called five times"); verify(mock, atLeast(2)).someMethod("was called at least two times"); //you can use flexible argument matchers, e.g: verify(mock, atLeastOnce()).someMethod(anyString());
使用
equals()
方法比较传递的参数。阅读ArgumentCaptor
或ArgumentMatcher
找出其他方式匹配/断言传递的参数。-
参数:
-
mock
- 待验证 -
mode
- times(x),atLeastOnce()或never()
返回:
- 模拟对象本身
-
-
重启
public static
void reset(T ... mocks) 智能Mockito用户很难使用这个功能,因为他们知道这可能是一个糟糕的测试的迹象。通常情况下,你不需要重置你的模拟,只是为每个测试方法创建新的模拟。不要
#reset()
考虑写一些简单,小而重点明确的测试方法,而不要考虑冗长的,过度规定的测试。 第一个潜在的代码气味正reset()
处于测试方法的中间。这可能意味着你测试太多了。按照你的测试方法的低语:“请保持我们的小而专注于单一的行为”。在mockito邮件列表上有几个线程。我们添加
reset()
方法的唯一原因是使用容器注入的模拟工作成为可能。欲了解更多信息,请参阅常见问题(这里)。不要伤害你自己
reset()
在测试方法的中间是一个代码气味(你可能测试太多)。List mock = mock(List.class); when(mock.size()).thenReturn(10); mock.add(1); reset(mock); //at this point the mock forgot any interactions & stubbing
-
类型参数:
-
T
- 嘲笑的类型
参数:
-
mocks
- 重置
-
-
clearInvocations
public static
void clearInvocations(T ... mocks) 使用这个方法只是为了清除调用,当存根是非平凡的。用例可以是:- 你正在使用依赖注入框架来注入你的模拟。
- 这个模拟是在有状态的情况下使用的。例如,一个类是独立的,这取决于你的模拟。
-
类型参数:
-
T
- 嘲笑的类型
参数:
-
mocks
- 嘲笑清除调用
-
verifyNoMoreInteractions
公共静态无效verifyNoMoreInteractions(对象 ...嘲笑)
检查是否有任何给定的模拟有任何未经验证的交互。你可以在验证你的模拟之后使用这个方法 - 确保你的模拟中没有其他的东西被调用。
另请参阅
never()
- 它更加明确,并充分传达意图。存根调用(如果调用)也被视为交互。
一句警告:谁做了很多经典的一些用户,期望-运行-验证嘲讽倾向于使用
verifyNoMoreInteractions()
非常频繁,甚至在每个测试方法。verifyNoMoreInteractions()
不建议在每个测试方法中使用。verifyNoMoreInteractions()
是交互测试工具包的一个方便的断言。只有在相关时才使用它。滥用它会导致过度指定,不易维护的测试。你可以在这里找到更多的阅读 。此方法还将检测在测试方法之前发生的未经验证的调用,例如:in
setUp()
,@Before
method或构造函数中。考虑编写漂亮的代码,只在测试方法中进行交互。例:
见的例子中的javadoc//interactions mock.doSomething(); mock.doSomethingUnexpected(); //verification verify(mock).doSomething(); //following will fail because 'doSomethingUnexpected()' is unexpected verifyNoMoreInteractions(mock);
Mockito
类-
参数:
-
mocks
- 待验证
-
-
verifyZeroInteractions
公共静态无效verifyZeroInteractions(对象 ...嘲笑)
验证除了先前验证的交互之外,在给定的模拟上没有发生交互。
这种方法具有相同的行为verifyNoMoreInteractions(Object...)
。-
参数:
-
mocks
- 待验证
-
-
doThrow
公共静态 Stubber doThrow(Throwable ... toBeThrown)
使用doThrow()
时要与存根异常的无效方法。when(Object)
由于编译器不喜欢方括号内的void方法 ,所以 需要使用不同的方法例:
doThrow(new RuntimeException()).when(mock).someVoidMethod();
-
参数:
-
toBeThrown
- 当被调用的方法被调用时被抛出
返回:
- stubber - 选择一个存根的方法
-
-
doThrow
公共静态 Stubber doThrow(Class <?extends Throwable > toBeThrown)
使用doThrow()
时要与存根异常的无效方法。将为每个方法调用创建一个新的异常实例。
when(Object)
由于编译器不喜欢方括号内的void方法 ,所以 需要使用不同的方法例:
doThrow(RuntimeException.class).when(mock).someVoidMethod();
-
参数:
-
toBeThrown
- 当被调用的方法被调用时被抛出
返回:
- stubber - 选择一个存根的方法 以来:
- 2.1.0
-
-
doThrow
public static Stubber doThrow(Class <?extends Throwable > toBeThrown, Class <?extends Throwable > ... toBeThrownNext)
与doThrow(Class)
设置连续的异常类相同。记住要使用doThrow()
时要存根的void方法抛出指定类的几个异常。将为每个方法调用创建一个新的异常实例。
when(Object)
由于编译器不喜欢方括号内的void方法 ,所以 需要使用不同的方法例:
doThrow(RuntimeException.class, BigFailure.class).when(mock).someVoidMethod();
-
参数:
-
toBeThrown
- 当被调用的方法被调用时被抛出 -
toBeThrownNext
- 当被调用的方法被调用时接下来被抛出
返回:
- stubber - 选择一个存根的方法 以来:
- 2.1.0
-
-
doCallRealMethod
public static Stubber doCallRealMethod()
使用doCallRealMethod()
时要调用真正执行的方法。像往常一样,您将阅读部分模拟警告:面向对象的编程通过将复杂性划分为单独的,特定的SRPy对象来解决更复杂的问题。部分模拟如何适应这种模式?那么,它只是不...部分模拟通常意味着复杂性已被移动到同一个对象上的不同方法。在大多数情况下,这不是您想要设计应用程序的方式。
但是,有些情况下,部分模拟会变得很方便:处理不能轻易更改的代码(第三方接口,传统代码的临时重构等)。但是,我不会使用部分模拟来实现新的,测试驱动的,设计的代码。
另请参阅javadoc
spy(Object)
以了解有关部分嘲讽的更多信息。 Mockito.spy()是创建部分模拟的推荐方法。 原因是它保证真正的方法被称为正确构造的对象,因为你负责构造传递给spy()方法的对象。例:
Foo mock = mock(Foo.class); doCallRealMethod().when(mock).someVoidMethod(); // this will call the real implementation of Foo.someVoidMethod() mock.someVoidMethod();
见的例子中的javadoc
Mockito
类-
返回:
- stubber - 选择一个存根的方法 以来:
- 1.9.5
-
doAnswer
公共静态 Stubber doAnswer(回答 )
使用doAnswer()
时要与存根通用空隙的方法Answer
。when(Object)
由于编译器不喜欢方括号内的void方法 ,所以 需要使用不同的方法例:
doAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); Mock mock = invocation.getMock(); return null; }}) .when(mock).someMethod();
见的例子中的javadoc
Mockito
类-
参数:
-
answer
- 在调用存根方法时回答
返回:
- stubber - 选择一个存根的方法
-
-
没做什么
公共静态 Stubber doNothing()
使用doNothing()
设置无效的方法什么也不做。 请注意,虚拟方法嘲笑默认情况下不做任何事情! 但是,在doNothing()方便的情况下,- 连续调用一个void方法:
doNothing(). doThrow(new RuntimeException()) .when(mock).someVoidMethod(); //does nothing the first time: mock.someVoidMethod(); //throws RuntimeException the next time: mock.someVoidMethod();
- 当你窥探真实的物体时,你想让void方法什么也不做:
List list = new LinkedList(); List spy = spy(list); //let's make clear() do nothing doNothing().when(spy).clear(); spy.add("one"); //clear() does nothing, so the list still contains "one" spy.clear();
见的例子中的javadoc
Mockito
类-
返回:
- stubber - 选择一个存根的方法
- 连续调用一个void方法:
-
doReturn
公共静态 Stubber doReturn(Object toBeReturned)
使用doReturn()
在那些极少数情况下,你不能使用when(Object)
。注意
when(Object)
总是建议用于存根,因为它是参数类型安全的,并且更具可读性(特别是在连续调用存根时)。以下是doReturn()方便使用的情况:
- 当间谍侦察真实的对象和调用真正的方法间谍带来的副作用
List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing: doReturn("foo").when(spy).get(0);
- 覆盖以前的例外情况:
when(mock.foo()).thenThrow(new RuntimeException()); //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown. when(mock.foo()).thenReturn("bar"); //You have to use doReturn() for stubbing: doReturn("bar").when(mock).foo();
见的例子中的javadoc
Mockito
类-
参数:
-
toBeReturned
- 当被调用的方法被调用时被返回
返回:
- stubber - 选择一个存根的方法
- 当间谍侦察真实的对象和调用真正的方法间谍带来的副作用
-
doReturn
公共静态 Stubber doReturn(Object toBeReturned, Object ... toBeReturnedNext)
相同doReturn(Object)
但设置要返回的连续值。请记住doReturn()
在不能使用的情况下使用 这些罕见的场合when(Object)
。注意
when(Object)
总是建议用于存根,因为它是参数类型安全的,并且更具可读性(特别是在连续调用存根时)。以下是doReturn()方便使用的情况:
- 当间谍侦察真实的对象和调用真正的方法间谍带来的副作用
List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo", "bar", "qix"); //You have to use doReturn() for stubbing: doReturn("foo", "bar", "qix").when(spy).get(0);
- 覆盖以前的例外情况:
when(mock.foo()).thenThrow(new RuntimeException()); //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown. when(mock.foo()).thenReturn("bar", "foo", "qix"); //You have to use doReturn() for stubbing: doReturn("bar", "foo", "qix").when(mock).foo();
见的例子中的javadoc
Mockito
类-
参数:
-
toBeReturned
- 当被调用的方法被调用时被返回 -
toBeReturnedNext
- 在调用存根方法时连续调用返回
返回:
- stubber - 选择一个存根的方法 以来:
- 2.1.0
- 当间谍侦察真实的对象和调用真正的方法间谍带来的副作用
-
为了
公共静态 InOrder inOrder (Object ... mocks)
创建InOrder
允许按顺序验证模拟的对象。
按顺序进行验证是非常灵活的 - 您不必 逐个 验证所有交互,只 需要验证您有兴趣测试的 所有交互。InOrder inOrder = inOrder(firstMock, secondMock); inOrder.verify(firstMock).add("was called first"); inOrder.verify(secondMock).add("was called second");
此外,您可以创建InOrder对象,只传递与按序验证相关的模拟。
InOrder
验证是“贪婪”的,但你几乎不会注意到它。如果你想了解更多,请阅读 这个维基页面。从Mockito 1.8.4开始,您可以按顺序验证NoMoreInvocations()。阅读更多:
InOrder.verifyNoMoreInteractions()
见的例子中的javadoc
Mockito
类-
参数:
-
mocks
- 按顺序核实
返回:
- InOrder对象用于按顺序进行验证
-
-
ignoreStubs
public static Object [] ignoreStubs(Object ... mocks)
为了验证,忽略了给定模拟的残留方法。有时加上verifyNoMoreInteractions()
或验证时有用inOrder()
。有助于避免冗余验证,通常我们对验证存根不感兴趣。警告,
ignoreStubs()
可能会导致过度使用verifyNoMoreInteractions(ignoreStubs(...));
Bear记住,Mockito不建议verifyNoMoreInteractions()
按照javadoc中概述的原因轰击每个测试。verifyNoMoreInteractions(Object...)
其他的话:所有* stubbed *方法的给定mock被标记*验证*,以便他们不进入verifyNoMoreInteractions()期间的一种方法。这种方法改变输入模拟!这个方法只是为了方便返回输入模拟。
包括在内的被忽略的存根也将被忽略用于验证
InOrder.verifyNoMoreInteractions()
。看第二个例子。例:
忽略存根可用于 验证顺序 ://mocking lists for the sake of the example (if you mock List in real you will burn in hell) List mock1 = mock(List.class), mock2 = mock(List.class); //stubbing mocks: when(mock1.get(0)).thenReturn(10); when(mock2.get(0)).thenReturn(20); //using mocks by calling stubbed get(0) methods: System.out.println(mock1.get(0)); //prints 10 System.out.println(mock2.get(0)); //prints 20 //using mocks by calling clear() methods: mock1.clear(); mock2.clear(); //verification: verify(mock1).clear(); verify(mock2).clear(); //verifyNoMoreInteractions() fails because get() methods were not accounted for. try { verifyNoMoreInteractions(mock1, mock2); } catch (NoInteractionsWanted e); //However, if we ignore stubbed methods then we can verifyNoMoreInteractions() verifyNoMoreInteractions(ignoreStubs(mock1, mock2)); //Remember that ignoreStubs() *changes* the input mocks and returns them for convenience.
List list = mock(List.class); when(mock.get(0)).thenReturn("foo"); list.add(0); System.out.println(list.get(0)); //we don't want to verify this list.clear(); InOrder inOrder = inOrder(ignoreStubs(list)); inOrder.verify(list).add(0); inOrder.verify(list).clear(); inOrder.verifyNoMoreInteractions();
-
参数:
-
mocks
- 输入模拟将被改变
返回:
- 同样的模拟参数传入 以来:
- 1.9.0
-
-
时
public static VerificationMode times(int wantedNumberOfInvocations)
允许验证确切的调用次数。例如:
见的例子中的javadocverify(mock, times(2)).someMethod("some arg");
Mockito
类-
参数:
-
wantedNumberOfInvocations
- 想要的调用次数
返回:
- 验证模式
-
-
决不
public static VerificationMode never()
别名times(0)
,看times(int)
验证交互没有发生。例如:
verify(mock, never()).someMethod();
如果你想验证没有任何与模拟检查
verifyZeroInteractions(Object...)
或互动verifyNoMoreInteractions(Object...)
见的例子中的javadoc
Mockito
类-
返回:
- 验证模式
-
至少一次
公共静态 验证模式 atLeastOnce()
允许至少一次验证。例如:
别名verify(mock, atLeastOnce()).someMethod("some arg");
atLeast(1)
。见的例子中的javadoc
Mockito
类-
返回:
- 验证模式
-
至少
公共静态 VerificationMode atLeast(int minNumberOfInvocations)
允许至少x验证。例如:
见的例子中的javadocverify(mock, atLeast(3)).someMethod("some arg");
Mockito
类-
参数:
-
minNumberOfInvocations
- 最少的调用次数
返回:
- 验证模式
-
-
最多
公共静态 VerificationMode atMost(int maxNumberOfInvocations)
允许进行最多x验证。例如:
见的例子中的javadocverify(mock, atMost(3)).someMethod("some arg");
Mockito
类-
参数:
-
maxNumberOfInvocations
- 最大的调用次数
返回:
- 验证模式
-
-
电话
公共静态 VerificationMode 调用(int wantedNumberOfInvocations)
按顺序进行非贪婪验证。例如inOrder.verify( mock, calls( 2 )).someMethod( "some arg" );
- 如果方法被调用3次不会失败,不像时间(2)
- 不会将第三次调用标记为已验证,不像atLeast(2)
-
参数:
-
wantedNumberOfInvocations
- 要验证的调用次数
返回:
- 验证模式
-
只要
public static VerificationMode only()
允许检查给定的方法是唯一被调用的方法。例如:verify(mock, only()).someMethod(); //above is a shorthand for following 2 lines of code: verify(mock).someMethod(); verifyNoMoreInvocations(mock);
也可以看看
verifyNoMoreInteractions(Object...)
见的例子中的javadoc
Mockito
类-
返回:
- 验证模式
-
时间到
公共静态 VerificationWithTimeout 超时(长毫秒)
允许超时验证。它会导致验证等待指定的时间段进行期望的交互,而不是立即失败,如果还没有发生。可能对并发条件下的测试有用。这不同于
after()
在()之后将等待整个周期,除非最后的测试结果是早期知道的(例如,如果一个never()失败),而timeout()将在验证通过后尽早停止,当使用时产生不同的行为与时间(2),例如,可以通过,然后失败。在这种情况下,超时将在时间(2)通过后立即传递,而在时间(2)失败后运行,然后失败。这个功能应该很少使用 - 找出测试你的多线程系统的更好方法。
见的例子中的javadoc//passes when someMethod() is called within given time span verify(mock, timeout(100)).someMethod(); //above is an alias to: verify(mock, timeout(100).times(1)).someMethod(); //passes as soon as someMethod() has been called 2 times before the given timeout verify(mock, timeout(100).times(2)).someMethod(); //equivalent: this also passes as soon as someMethod() has been called 2 times before the given timeout verify(mock, timeout(100).atLeast(2)).someMethod(); //verifies someMethod() within given time span using given verification mode //useful only if you have your own custom verification modes. verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
Mockito
类-
参数:
-
millis
- - 以毫秒为单位的时间跨度
返回:
- 验证模式
-
-
后
(long millis)之后的公共静态 VerificationAfterDelay
允许在给定的时间内进行验证。它会导致验证等待指定的时间段进行所需的交互,而不是立即失败(如果尚未发生)。可能对并发条件下的测试有用。这不同于
timeout()
在()之后等待整个周期,而timeout()将在验证通过后立即提前停止,在与时间(2)一起使用时产生不同的行为,例如,可以通过然后失败。在这种情况下,超时会在时间(2)通过后立即传递,而在之后的时间将运行整个时间,哪个时间点将失败,因为时间(2)失败。这个功能应该很少使用 - 找出测试你的多线程系统的更好方法。
尚未实施以使用InOrder验证。
见的例子中的javadoc//passes after 100ms, if someMethod() has only been called once at that time. verify(mock, after(100)).someMethod(); //above is an alias to: verify(mock, after(100).times(1)).someMethod(); //passes if someMethod() is called *exactly* 2 times after the given timespan verify(mock, after(100).times(2)).someMethod(); //passes if someMethod() has not been called after the given timespan verify(mock, after(100).never()).someMethod(); //verifies someMethod() after a given time span using given verification mode //useful only if you have your own custom verification modes. verify(mock, new After(100, yourOwnVerificationMode)).someMethod();
Mockito
类-
参数:
-
millis
- - 以毫秒为单位的时间跨度
返回:
- 验证模式
-
-
validateMockitoUsage
公共静态无效validateMockitoUsage()
首先,如果遇到任何问题,我建议您阅读Mockito FAQ: https: //github.com/mockito/mockito/wiki/FAQ如有疑问,您也可以发送到mockito邮件列表:http://groups.google.com/group/mockito
validateMockitoUsage()
明确验证框架状态以检测Mockito的无效使用。不过,这个功能是可选的,因为Mockito始终验证使用情况...但是有一个小问题需要阅读。错误使用的例子:
如果你滥用Mockito会抛出异常,这样你就知道你的测试是否写得正确。问题是Mockito 在下一次 使用框架时会进行验证(例如,下一次验证,存根,调用模拟等)。但是,即使在下一次测试中可能会抛出异常,异常 消息中 也会 包含一个带有缺陷位置的 可导航堆栈跟踪元素。因此,您可以点击并找到Mockito被滥用的地方。//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);
有时候,你可能想明确地验证框架的用法。例如,其中一个用户想要投入
validateMockitoUsage()
他的@After
方法,以便他在误用Mockito时立即知道。没有它,他会早在下一次他就使用这个框架就知道了。validateMockitoUsage()
进入的另外一个好处@After
是,jUnit跑步者和规则在测试方法中总会失败,而普通的“下一次”验证可能会使下一个测试方法失败。但即使JUnit可能会将下一个测试报告为红色,也不要担心,只需单击异常消息中的可导航堆栈跟踪元素即可找到您误用mockito的地方。内置runner
MockitoJUnitRunner
和规则:MockitoRule
在每个测试方法之后,执行validateMockitoUsage()。请记住,通常情况下,您不必
validateMockitoUsage()
在下一次触发框架验证时就足够了,这主要是因为增强了异常消息和可点击的缺陷位置。但是,如果您已经拥有足够的测试基础架构(比如您自己的所有测试的运行者或基类),那么我会推荐使用validateMockitoUsage(),因为添加了一个特殊的操作来实现@After
零成本。见的例子中的javadoc
Mockito
类
-
withSettings
public static MockSettings withSettings()
允许使用附加的模拟设置进行模拟创建。不要经常使用它。考虑编写使用简单模拟的简单测试。重复我之后:简单的测试推简单,KISSy,可读和可维护的代码。如果你不能以简单的方式编写测试 - 重构测试中的代码。
模拟设置的例子:
//Creates mock with different default answer & name Foo mock = mock(Foo.class, withSettings() .defaultAnswer(RETURNS_SMART_NULLS) .name("cool mockie")); //Creates mock with different default answer, descriptive name and extra interfaces Foo mock = mock(Foo.class, withSettings() .defaultAnswer(RETURNS_SMART_NULLS) .name("cool mockie") .extraInterfaces(Bar.class));
MockSettings
已经出现了两个原因。首先,当需求到来时,很容易添加另一个模拟设置。其次,为了能够结合不同的模拟设置而不需要引入大量的重载模拟()方法。查看javadoc
MockSettings
了解可能的模拟设置。-
返回:
- 模拟设置实例与默认值。
-
描述
public static VerificationMode description(String description)
如果验证失败,则添加要打印的说明。verify(mock, description("This will print on failure")).someMethod("some arg");
-
参数:
-
description
- 描述打印失败。
返回:
- 验证模式 以来:
- 2.1.0
-
-
骨架
@Incubating 公共静态 MockitoFramework 框架()
对于高级用户或框架集成商。见MockitoFramework
课。-
以来:
- 2.1.0
-
mockitoSession
@Incubating public static MockitoSessionBuilder mockitoSession()
MockitoSession
是一个可选的强烈推荐的功能,通过消除样板代码和添加额外的验证来帮助推动清洁测试。
-
-