公共类Mockito 扩展了ArgumentMatchers
这个javadoc内容也能够在http://mockito.org的网页上找到。全部的文档都保存在javadoc中,由于它保证了网页内容与源代码内容的一致性。即便脱机工做,它也容许直接从IDE访问文档。它激励Mockito开发人员随时随地记录他们编写的代码,天天都提交。html
@Mock
注释doReturn()
| doThrow()
| doAnswer()
| doNothing()
| doCallRealMethod()
方法家族@Captor
,@Spy
,@InjectMocks
(因为1.8。 3)@Spies
,@InjectMocks
并构造注射善(因为1.9.0)MockMaker
API(从1.9.5开始)repositories {
jcenter()
}
dependencies {
testCompile "org.mockito:mockito-core:+" androidTestCompile "org.mockito:mockito-android:+" }
您能够继续在常规虚拟机上运行相同的单元测试,在上面显示的“testCompile”范围内使用“mockito-core”工件。请注意,因为Android VM的限制,您没法使用Android上的
内联模拟器
。若是您在Android上遇到模拟问题,请
在官方问题跟踪器上
打开一个问题 。请提供您正在使用的Android版本和项目的相关性。
repositories {
jcenter()
}
dependencies {
testCompile "org.mockito:mockito-inline:+" }
请注意,当内联模拟功能被集成到默认模拟器中时,这个工件可能会被废除。
有关内联模拟的更多信息,请参阅第39节。java
add()
,
get()
,
clear()
方法)。
//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();
一旦建立,模拟将记住全部的交互。而后,您能够选择性地验证您感兴趣的任何互动。android
//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);
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
git
有关自定义参数匹配器的信息,请查看javadoc的ArgumentMatcher
类。github
使用复杂的参数匹配是合理的。equals()
与偶尔anyX()
匹配使用的天然匹配风格倾向于给干净和简单的测试。有时候重构代码以容许equals()
匹配甚至实现equals()
方法来帮助进行测试会更好。正则表达式
另外,阅读第15节或javadoc的ArgumentCaptor
类。 ArgumentCaptor
是参数匹配器的一个特殊的实现,捕获进一步的断言的参数值。spring
参数匹配器警告:编程
若是使用参数匹配器,全部参数都必须由匹配器提供。json
如下示例显示验证,但一样适用于存根:api
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()
验证/存根方法以外的方法。
//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)能够省略。
doThrow(new RuntimeException()).when(mockedList).clear(); //following throws RuntimeException: mockedList.clear();
阅读更多关于
doThrow()
|
doAnswer()
家庭在方法
第12
。
// 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对象,仅传递与按序验证相关的模拟。
//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);
//using mocks mockedList.add("one"); mockedList.add("two"); verify(mockedList).add("one"); //following verification will fail verifyNoMoreInteractions(mockedList);
一句
警告
:谁作了不少经典的一些用户,指望-运行-验证嘲讽倾向于使用
verifyNoMoreInteractions()
很是频繁,甚至在每一个测试方法。
verifyNoMoreInteractions()
不建议在每一个测试方法中使用。
verifyNoMoreInteractions()
是交互测试工具包的一个方便的断言。只有在相关时才使用它。滥用它会致使
过分指定
,
不易维护的
测试。你能够
在这里
找到更多的阅读 。
另请参阅never()
- 它更加明确,并充分传达意图。
@Mock
注释public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider; private ArticleManager manager;
重要!
这须要在基类或测试运行的某个地方:
MockitoAnnotations.initMocks(testClass);你可使用内置的runner:
MockitoJUnitRunner
或者一个规则:
MockitoRule
。
在这里阅读更多: MockitoAnnotations
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")
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"));
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()
全部您的存根呼叫。
阅读更多关于这些方法:
真正的间谍应该谨慎地偶尔使用,例如在处理遗留代码时。
对真实物体的窥视可能与“部分嘲讽”概念有关。 在释放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);
这是默认的答案,因此只有当你不存在方法调用时才会使用它。
Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
阅读更多关于这个有趣的答案的答案:RETURNS_SMART_NULLS
equals()
方法。这也是推荐的参数匹配方式,由于它使测试变得简单明了。可是,在某些状况下,在实际验证以后对某些论点做出断言是有帮助的。例如:
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());
警告:
建议使用ArgumentCaptor进行验证,
但不要
使用stubbing。使用带有stub的ArgumentCaptor可能会下降测试可读性,由于在assert(也就是验证或'then')块以外建立了捕获器。也能够减小缺陷定位,由于若是不调用stubbed方法,则不会捕获任何参数。
ArgumentCaptor与自定义参数匹配器相关(请参阅ArgumentMatcher
类javadoc )。这两种技术均可以用来肯定传递给mock的某些参数。不过,ArgumentCaptor可能更适合如下状况:
ArgumentMatcher
一般更适合于存根。
在发布以前,1.8版本 spy()
并无产生真正的部分嘲讽,这让一些用户感到困惑。阅读更多关于间谍:在这里或在javadoc的spy(Object)
方法。
//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();
像往常同样,您将阅读
部分模拟警告
:面向对象的编程经过将复杂性划分为单独的,特定的SRPy对象来解决更复杂的问题。部分模拟如何适应这种模式?那么,它只是不...部分模拟一般意味着复杂性已被移动到同一个对象上的不一样方法。在大多数状况下,这不是您想要设计应用程序的方式。
可是,有些状况下,部分模拟会变得很方便:处理不能轻易更改的代码(第三方接口,传统代码的临时重构等)。可是,我不会使用部分模拟来实现新的,测试驱动的,设计的代码。
不要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
若有疑问,您也能够发送到mockito邮件列表:http: //groups.google.com/group/mockito
接下来,您应该知道Mockito会验证您是否始终正确使用它。可是,有一个问题,因此请阅读javadocvalidateMockitoUsage()
在这里开始了解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()); }
警告:这应该不多用于单元测试。
该行为是针对具备不可靠外部依赖性的BDD规范的特定用例实现的。这是在Web环境中,来自外部依赖项的对象正在被序列化以在层之间传递。
要建立可串行化的模拟使用MockSettings.serializable()
:
List serializableMock = mock(List.class, withSettings().serializable());
模拟能够被序列化,假设全部正常的 序列化要求都获得了这个类的知足。
由于间谍(...)方法没有一个接受MockSettings的重载版本,因此制做一个真正的对象间谍序列化是一个更多的努力。不用担忧,你几乎不会使用它。
List<Object> list = new ArrayList<Object>(); List<Object> spy = mock(ArrayList.class, withSettings() .spiedInstance(list) .defaultAnswer(CALLS_REAL_METHODS) .serializable());
@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
。
容许超时验证。它会致使验证等待指定的时间段进行指望的交互,而不是当即失败,若是尚未发生。可能对并发条件下的测试有用。
这个功能应该不多使用 - 找出测试你的多线程系统的更好方法。
还没有实施以使用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();
@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;
Mockito如今可让你建立嘲讽时。基本上,它容许在一行代码中建立一个存根。这能够有助于保持测试代码的清洁。例如,一个无聊的存根能够在测试中的字段初始化时建立和存根:
public class CarTest { Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock(); @Test public void should... {}
为了验证,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...)
Mockito提供API来检查模拟对象的细节。这个API对高级用户和模拟框架集成商颇有用。
//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());
欲了解更多信息,请参阅javadoc
MockingDetails
。
对于使用一般的间谍API 很难嘲笑或间谍的对象的间谍或部分嘲笑是有用的。自从Mockito 1.10.11以后,表明可能会或可能不会与模拟类型相同。若是类型不一样,则须要在委托类型上找到匹配的方法,不然抛出异常。这个功能的可能用例:
与普通间谍的区别:
spy(Object)
)包含spied实例的全部状态,而且在spy上调用方法。侦察实例只用于模拟建立从状态复制。若是你对一个普通间谍调用一个方法,而且在内部调用这个间谍的其余方法,那么这些调用就会被记住进行验证,而且能够被有效地删除。在文档中查看更多信息AdditionalAnswers.delegatesTo(Object)
。
MockMaker
API(自1.9.5以来)受谷歌Android家伙的要求和补丁的驱动,Mockito如今提供了一个扩展点,容许替换代理生成引擎。默认状况下,Mockito使用Byte Buddy 建立动态代理。
扩展点是为了扩展Mockito的高级用户。例如,如今可使用针对的Mockito Android的测试与帮助dexmaker。
欲了解更多细节,动机和例子请参阅文档MockMaker
。
given(dog.bark()).willReturn(2); // when ... then(person).should(times(2)).ride(bike);
有关更多信息和示例,请参阅
BDDMockito.then(Object)
}
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<foo, bar=""> 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...)
。
// use regular serialization mock(Book.class, withSettings().serializable()); // use serialization across classloaders mock(Book.class, withSettings().serializable(ACROSS_CLASSLOADERS));
欲了解更多详情,请参阅
MockSettings.serializable(SerializableMode)
。
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();
请注意,在大多数状况下,模拟返回模拟是错误的。
@Mock
@Spy
@InjectMocks
@RunWith
(MockitoJUnitRunner
.class)
MockitoAnnotations.initMocks(Object)
在该方法中调用@Before
@RunWith(YetAnotherRunner.class) public class TheTest { @Rule public MockitoRule mockito = MockitoJUnit.rule(); // ... }
更多信息请参阅
MockitoJUnit.rule()
。
PluginSwitch
。
若是验证失败,容许指定要打印的自定义消息。
例子:
// 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();
您可使用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);
因为Answer
接口只有一个方法,因此已经能够在很是简单的状况下使用lambda表达式在Java 8中实现它。您须要使用方法调用的参数的次数越多,您须要更多地对参数进行类型转换InvocationOnMock
。
例子:
// 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());
为了方便起见,能够将使用方法调用参数的自定义答案/操做编写为Java 8 lambda表达式。即便在Java 7中,基于类型化界面的这些自定义答案也能够减小样板。特别是,这种方法将使测试使用回调函数更容易。方法
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.<string,callback>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<string, callback="">() { 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.<boolean,string,string>answer((input1, input2) -> input1.equals(input2)))) .when(mock).execute(anyString(), anyString()); // Java 7 doAnswer(answer(new Answer2<string, string,="" string="">() { public String answer(String input1, String input2) { return input1 + input2; }})).when(mock).execute(anyString(), anyString());
Mockito如今保留对嘲笑的方法和类型以及通用元数据的注释。之前,模拟类型不保留对类型的注释,除非它们是显式继承的,而且永远不会在方法上保留注释。所以,如今下列条件成立:
@MyAnnotation class Foo { List<String> bar() { ... } } Class<?> mockType = mock(Foo.class).getClass(); assert mockType.isAnnotationPresent(MyAnnotation.class); assert mockType.getDeclaredMethod("bar").getGenericReturnType() instanceof ParameterizedType;
MyAnnotation class Foo { List<String> bar() { ... } } Class<?> mockType = mock(Foo.class).getClass(); assert mockType.isAnnotationPresent(MyAnnotation.class); assert mockType.getDeclaredMethod("bar").getGenericReturnType() instanceof ParameterizedType;
当使用Java 8时,Mockito如今也保留了类型注释。这是默认行为,若是使用替代方法可能不会成立MockMaker
。
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
方法-javaagent
。若是你对这个功能的更多细节感兴趣,请阅读javadoc org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
MockitoRule.strictness(Strictness)
与Strictness.STRICT_STUBS
MockitoJUnitRunner.StrictStubs
MockitoSession
MockitoJUnitRunner
MockitoHint
默认状况下,“松散”使得Mockito测试有时难以调试。在某些状况下,错误配置的桩(如使用错误的参数)会强制用户使用调试器运行测试。理想状况下,测试失败是显而易见的,不须要调试器来肯定根本缘由。从版本2.1开始,Mockito已经得到了将框架推向“严格”的新功能。咱们但愿Mockito可以提供出色的可调试性,同时不会失去其核心嘲笑风格,并针对直观性,清晰度和清晰的测试代码进行了优化。
帮助Mockito!尝试新功能,给咱们反馈,参加GitHub 第769期关于Mockito严格性的讨论 。
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。VerificationStartedListener
并VerificationStartedEvent
启用框架集成器来替换模拟对象以进行验证。主要的驱动用例是Spring Boot集成。有关详细信息,请参阅Javadoc VerificationStartedListener
。MockSettings.verificationStartedListeners(VerificationStartedListener...)
容许在模拟建立时提供验证开始的听众。MockingDetails.getMock()
添加了新的方便的方法,使MockingDetails
API更完整。咱们发现这个方法在实现过程当中颇有用。修饰符和类型 | 字段和说明 |
---|---|
static Answer<Object> |
CALLS_REAL_METHODS
|
static Answer<Object> |
RETURNS_DEEP_STUBS
|
static Answer<Object> |
RETURNS_DEFAULTS
Answer
每一个模拟的默认值,
若是
模拟不被扼杀。
|
static Answer<Object> |
RETURNS_MOCKS
|
static Answer<Object> |
RETURNS_SELF
|
static Answer<Object> |
RETURNS_SMART_NULLS
|
构造函数和说明 |
---|
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 <T> void |
clearInvocations(T... mocks)
使用这个方法只是为了清除调用,当存根是非平凡的。
|
static VerificationMode |
description(String description)
若是验证失败,则添加要打印的说明。
|
static Stubber |
doAnswer(Answer answer)
|
static Stubber |
doCallRealMethod()
使用
doCallRealMethod()
时要调用真正执行的方法。
|
static Stubber |
doNothing()
使用
doNothing()
设置无效的方法什么也不作。
|
static Stubber |
doReturn(Object toBeReturned)
|
static Stubber |
doReturn(Object toBeReturned, Object... toBeReturnedNext)
|
static Stubber |
doThrow(Class<? extends Throwable> toBeThrown)
使用
doThrow()
时要与存根异常的无效方法。
|
static Stubber |
doThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... toBeThrownNext)
|
static Stubber |
doThrow(Throwable... toBeThrown)
使用
doThrow()
时要与存根异常的无效方法。
|
static MockitoFramework |
framework()
对于高级用户或框架集成商。
|
static Object[] |
ignoreStubs(Object... mocks)
为了验证,忽略了给定模拟的残留方法。
|
static InOrder |
inOrder(Object... mocks)
|
static <T> T |
mock(Class<T> classToMock)
建立给定的类或接口的模拟对象。
|
static <T> T |
mock(Class<T> classToMock, Answer defaultAnswer)
建立一个指定的策略模拟其交互的答案。
|
static <T> T |
mock(Class<T> classToMock, MockSettings mockSettings)
用一些非标准设置建立一个模拟。
|
static <T> T |
mock(Class<T> classToMock, String name)
指定模拟名称。
|
static MockingDetails |
mockingDetails(Object toInspect)
返回一个MockingDetails实例,该实例能够检查特定对象的Mockito相关信息。
|
static MockitoSessionBuilder |
mockitoSession()
MockitoSession
是一个可选的强烈推荐的功能,经过消除样板代码和添加额外的验证来帮助推进清洁测试。
|
static VerificationMode |
never()
|
static VerificationMode |
only()
容许检查给定的方法是惟一被调用的方法。
|
static <T> void |
reset(T... mocks)
智能Mockito用户很难使用这个功能,由于他们知道这多是一个糟糕的测试的迹象。
|
static <T> T |
spy(Class<T> classToSpy)
|
static <T> 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/FAQ
|
static <T> T |
verify(T mock)
验证
一次发生的
某些行为。
|
static <T> T |
verify(T mock, VerificationMode mode)
验证某些行为发生至少一次/确切的次数/从不。
|
static void |
verifyNoMoreInteractions(Object... mocks)
检查是否有任何给定的模拟有任何未经验证的交互。
|
static void |
verifyZeroInteractions(Object... mocks)
|
static <T> OngoingStubbing<T> |
when(T methodCall)
启用存根方法。
|
static MockSettings |
withSettings()
容许使用附加的模拟设置进行模拟建立。
|
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
public static final Answer < Object > RETURNS_DEFAULTS
Answer
每一个模拟的默认值,
若是
模拟不被扼杀。一般它只是返回一些空的值。
Answer
能够用来定义未打开的调用的返回值。
此实现首先尝试全局配置,若是没有全局配置,则将使用返回零,空集合,空值等的默认答案。
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.
public static final Answer: < Object > RETURNS_MOCKS
Answer
用于
mock(Class, Answer)
Answer
能够用来定义未打开的调用的返回值。
这个实如今处理遗留代码时会颇有帮助。
ReturnsMocks首先尝试返回普通的值(零,空集合,空字符串等),而后尝试返回模拟。若是返回类型不能被模拟(例如final),则null
返回plain 。
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类型的系统。
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();
public static final Answer < Object > RETURNS_SELF
Answer
用于
mock(Class, Answer)
。当一个方法被调用返回一个Type等于该类或一个超类的方法时,容许Builder mock返回自身。
请记住,这个答案使用方法的返回类型。若是这个类型能够分配给模拟类,它将返回模拟。所以,若是你有一个方法返回一个超类(例如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<String> headers; public HttpBuilder() { this.headers = new ArrayList<String>(); } 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); }
public static <T> T mock(Class <T> classToMock)
见的例子中的javadoc Mockito
类
classToMock
- 类或接口来模拟
public static <T> T mock(Class <T> classToMock, String name)
请注意,命名模拟不适用于使用太多模拟或协做者的复杂代码。 若是你有太多的mock,那么重构代码,这样很容易测试/调试,而没必要命名模拟。
若是你使用@Mock
注释,那么你已经免费命名模拟! @Mock
使用字段名称做为模拟名称。Read more.
见的例子中的javadoc Mockito
类
classToMock
- 类或接口来模拟
name
- 模拟
公共静态 MockingDetails mockingDetails(Object toInspect)
在未来的Mockito版本中,MockingDetails可能会增加,并提供有关模拟的其余有用信息,例如调用,存根信息等。
toInspect
- - 检查对象。空输入是容许的。
MockingDetails
实例。
public static <T> T mock(Class <T> 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> T mock(Class <T> 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间谍(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);
见的例子中的javadoc Mockito
类
请注意,间谍不会有任何关于间谍类型的注释,由于CGLIB不会重写它们。对于依靠间谍来得到这些注释的代码来讲,可能会很麻烦。
object
- 监视
@Incubating public static <T> T spy(Class <T> 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
- 要窥探的班级
public static <T> OngoingStubbing <T> when(T methodCall)
简单地说:“ 当 x方法被调用,而后返回y”。
例子:
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();
有关throwables的void方法,请参见:
doThrow(Throwable...)
能够覆盖桩号:例如,普通桩能够进入夹具设置,但测试方法能够覆盖它。请注意,覆盖残片是一种潜在的代码异味,指出了太多的残片。
一旦被存根,该方法将老是返回存根值,而无论被调用的次数多少。
最后的茬更重要 - 当你屡次用相同的参数扼杀相同的方法。
尽管能够验证存根调用,但一般这只是多余的。比方说,你已经残废了foo.bar()
。若是你的代码关心什么foo.bar()
返回,那么别的东西就会中断(一般在verify()
执行以前)。若是你的代码不在意什么get(0)
返回,那么它不该该被扼杀。不服气?看到这里。
见的例子中的javadoc Mockito
类
methodCall
- 方法被扼杀
public static <T> 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验证(T模拟, VerificationMode 模式)
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());
次(1)是默认值
,能够省略
使用equals()
方法比较传递的参数。阅读ArgumentCaptor
或ArgumentMatcher
找出其余方式匹配/断言传递的参数。
mock
- 待验证
mode
- times(x),atLeastOnce()或never()
public static <T> void reset(T ... mocks)
不要#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
- 重置
public static <T> void clearInvocations(T ... mocks)
T
- 嘲笑的类型
mocks
- 嘲笑清除调用
公共静态无效verifyNoMoreInteractions(对象 ...嘲笑)
你能够在验证你的模拟以后使用这个方法 - 确保你的模拟中没有其余的东西被调用。
另请参阅never()
- 它更加明确,并充分传达意图。
存根调用(若是调用)也被视为交互。
一句警告:谁作了不少经典的一些用户,指望-运行-验证嘲讽倾向于使用verifyNoMoreInteractions()
很是频繁,甚至在每一个测试方法。 verifyNoMoreInteractions()
不建议在每一个测试方法中使用。verifyNoMoreInteractions()
是交互测试工具包的一个方便的断言。只有在相关时才使用它。滥用它会致使过分指定,不易维护的测试。你能够在这里找到更多的阅读 。
此方法还将检测在测试方法以前发生的未经验证的调用,例如:in setUp()
,@Before
method或构造函数中。考虑编写漂亮的代码,只在测试方法中进行交互。
例:
//interactions mock.doSomething(); mock.doSomethingUnexpected(); //verification verify(mock).doSomething(); //following will fail because 'doSomethingUnexpected()' is unexpected verifyNoMoreInteractions(mock);
见的例子中的javadoc
Mockito
类
mocks
- 待验证
公共静态无效verifyZeroInteractions(对象 ...嘲笑)
mocks
- 待验证
公共静态 Stubber doThrow(Throwable ... toBeThrown)
doThrow()
时要与存根异常的无效方法。
when(Object)
因为编译器不喜欢方括号内的void方法 ,因此 须要使用不一样的方法
例:
doThrow(new RuntimeException()).when(mock).someVoidMethod();
toBeThrown
- 当被调用的方法被调用时被抛出
公共静态 Stubber doThrow(Class <?extends Throwable > toBeThrown)
doThrow()
时要与存根异常的无效方法。
将为每一个方法调用建立一个新的异常实例。
when(Object)
因为编译器不喜欢方括号内的void方法 ,因此 须要使用不一样的方法
例:
doThrow(RuntimeException.class).when(mock).someVoidMethod();
toBeThrown
- 当被调用的方法被调用时被抛出
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
- 当被调用的方法被调用时接下来被抛出
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 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 doNothing()
doNothing()
设置无效的方法什么也不作。
请注意,虚拟方法嘲笑默认状况下不作任何事情!
可是,在doNothing()方便的状况下,
doNothing().
doThrow(new RuntimeException()) .when(mock).someVoidMethod(); //does nothing the first time: mock.someVoidMethod(); //throws RuntimeException the next time: mock.someVoidMethod();
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 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(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
- 在调用存根方法时连续调用返回
公共静态 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
- 按顺序核实
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
- 输入模拟将被改变
public static VerificationMode times(int wantedNumberOfInvocations)
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)
minNumberOfInvocations
- 最少的调用次数
公共静态 VerificationMode atMost(int maxNumberOfInvocations)
maxNumberOfInvocations
- 最大的调用次数
公共静态 VerificationMode 调用(int wantedNumberOfInvocations)
inOrder.verify( mock, calls( 2 )).someMethod( "some arg" );
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)失败后运行,而后失败。
这个功能应该不多使用 - 找出测试你的多线程系统的更好方法。
//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();
见的例子中的javadoc
Mockito
类
millis
- - 以毫秒为单位的时间跨度
(long millis)以后的公共静态 VerificationAfterDelay
这不一样于timeout()
在()以后等待整个周期,而timeout()将在验证经过后当即提早中止,在与时间(2)一块儿使用时产生不一样的行为,例如,能够经过而后失败。在这种状况下,超时会在时间(2)经过后当即传递,而在以后的时间将运行整个时间,哪一个时间点将失败,由于时间(2)失败。
这个功能应该不多使用 - 找出测试你的多线程系统的更好方法。
还没有实施以使用InOrder验证。
//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();
见的例子中的javadoc
Mockito
类
millis
- - 以毫秒为单位的时间跨度
公共静态无效validateMockitoUsage()
若有疑问,您也能够发送到mockito邮件列表:http://groups.google.com/group/mockito
validateMockitoUsage()
明确验证框架状态以检测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);
若是你滥用Mockito会抛出异常,这样你就知道你的测试是否写得正确。问题是Mockito
在下一次
使用框架时会进行验证(例如,下一次验证,存根,调用模拟等)。可是,即便在下一次测试中可能会抛出异常,异常
消息中
也会包含一个带有缺陷位置的可导航堆栈跟踪元素。所以,您能够点击并找到Mockito被滥用的地方。
有时候,你可能想明确地验证框架的用法。例如,其中一个用户想要投入validateMockitoUsage()
他的@After
方法,以便他在误用Mockito时当即知道。没有它,他会早在下一次他就使用这个框架就知道了。validateMockitoUsage()
进入的另一个好处@After
是,jUnit跑步者和规则在测试方法中总会失败,而普通的“下一次”验证可能会使下一个测试方法失败。但即便JUnit可能会将下一个测试报告为红色,也不要担忧,只需单击异常消息中的可导航堆栈跟踪元素便可找到您误用mockito的地方。
内置runner MockitoJUnitRunner
和规则:MockitoRule
在每一个测试方法以后,执行validateMockitoUsage()。
请记住,一般状况下,您没必要validateMockitoUsage()
在下一次触发框架验证时就足够了,这主要是由于加强了异常消息和可点击的缺陷位置。可是,若是您已经拥有足够的测试基础架构(好比您本身的全部测试的运行者或基类),那么我会推荐使用validateMockitoUsage(),由于添加了一个特殊的操做来实现@After
零成本。
见的例子中的javadoc Mockito
类
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
- 描述打印失败。
@Incubating 公共静态 MockitoFramework 框架()
@Incubating public static MockitoSessionBuilder mockitoSession()
MockitoSession
是一个可选的强烈推荐的功能,经过消除样板代码和添加额外的验证来帮助推进清洁测试。