公共類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
是一個可選的強烈推薦的功能,經過消除樣板代碼和添加額外的驗證來幫助推進清潔測試。