Mockito 中文文檔 ( 2.0.26 beta )
因爲缺少校對,不免有謬誤之處,若是發現任何語句不通順、翻譯錯誤,均可以在github中的項目提出issue。謝謝~html
Mockito框架官方地址mockito,文檔地址。java
Mockito庫可以Mock對象、驗證結果以及打樁(stubbing)。git
該文檔您也能夠經過http://mockito.org獲取到。全部文檔都保存在javadocs中,由於它可以保證文檔與源代碼的一致性。這樣也可以讓離線的用戶從IDE直接訪問到文檔。這樣一來也可以激勵Mockito開發者在每次寫代碼、每次提交時更新對應的文檔。程序員
參與人員
成員 | 任務 |
---|---|
Mr.Simple | 1-15 |
chaosss | 16-26 |
tiiime | 27~35 |
dengshiwei | a~c開頭的方法,包含 |
objectlife | d~m開頭的方法 |
Conquer | n-w開頭的函數 |
目錄
- 遷移到Mockito 2.0
- 驗證某些行爲
- 如何作一些測試樁 (Stub)
- 參數匹配器 (matchers)
- 驗證函數的確切、最少、從未調用次數
- 爲返回值爲void的函數經過Stub拋出異常
- 按照順序驗證執行結果
- 確保交互(interaction)操做不會執行在mock對象上
- 查找冗餘的調用
- 簡化mock對象的建立
- 爲連續的調用作測試樁 (stub)
- 爲回調作測試樁
- doReturn()、doThrow()、doAnswer()、doNothing()、doCallRealMethod()系列方法的運用
- 監控真實對象
- 修改沒有測試樁的調用的默認返回值 ( 1.7版本以後 )
- 爲下一步的斷言捕獲參數 (1.8版本以後)
- 真實的局部mocks (1.8版本以後)
- 重置mocks對象 (1.8版本以後)
- 故障排查與驗證框架的使用 (1.8版本以後)
- 行爲驅動開發的別名 (1.8版本以後)
- 序列化mock對象
- 新的註解 : @Captor,@Spy,@ InjectMocks (1.8.3版本以後)
- 驗證超時 (1.8.5版本以後)
- 自動初始化被@Spies, @InjectMocks註解的字段以及構造函數注入 (1.9.0版本以後)
- 單行測試樁 (1.9.0版本以後)
- 驗證被忽略的測試樁 (1.9.0版本以後)
- mock詳情 (1.9.5版本以後)
- delegate調用真實的實例 (1.9.5版本以後)
- MockMaker API (1.9.5版本以後)
- BDD風格的驗證 (1.10.0版本以後)
- 追蹤或者Mock抽象類 (1.10.12版本以後)
- Mockito mock對象經過ClassLoader能被序列化/反序列化 (1.10.0版本以後)
- deep stubs更好的支持泛型 (1.10.0版本以後)
- Mockito JUnit 規則 (1.10.17版本以後)
- 開/關插件 (1.10.15版本以後)
- 自定義驗證失敗消息 (2.0.0版本以後)
0. 遷移到Mockito 2.0
爲了持續提高Mockito以及更進一步的提高單元測試體驗,咱們但願你升級到Mockito 2.0.Mockito遵循語意化的版本控制,除非有很是大的改變纔會變化主版本號。在一個庫的生命週期中,爲了引入一系列有用的特性,修改已存在的行爲或者API等重大變動是在所不免的。所以,咱們但願你可以愛上 Mockito 2.0!github
重要變動 :編程
- Mockito從Hamcrest中解耦,自定義的matchers API也發生了改變,查看ArgumentMatcher 的基本原理以及遷移指南。
跟着咱們的示例來mock 一個List,由於你們都知道它的接口(例如add(),get(), clear())。不要mock一個真實的List類型,使用一個真實的實例來替代。api
1. 驗證某些行爲
// 靜態導入會使代碼更簡潔
import static org.mockito.Mockito.*;
// mock creation 建立mock對象
List mockedList = mock(List.class);
//using mock object 使用mock對象
mockedList.add("one");
mockedList.clear();
//verification 驗證
verify(mockedList).add("one");
verify(mockedList).clear();
一旦mock對象被建立了,mock對象會記住全部的交互。而後你就可能選擇性的驗證你感興趣的交互。安全
如何作一些測試樁 (Stub)
2. //You can mock concrete classes, not only interfaces
// 你能夠mock具體的類型,不只只是接口
LinkedList mockedList = mock(LinkedList.class);
//stubbing
// 測試樁
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());
//following prints "first"
// 輸出「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
// 由於get(999) 沒有打樁,所以輸出null
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 before even verify() gets executed).
//If your code doesn't care what get(0) returns then it should not be stubbed. Not convinced? See here.
// 驗證get(0)被調用的次數
verify(mockedList).get(0);
- 默認狀況下,全部的函數都有返回值。mock函數默認返回的是null,一個空的集合或者一個被對象類型包裝的內置類型,例如0、false對應的對象類型爲Integer、Boolean;
- 測試樁函數能夠被覆寫 : 例如常見的測試樁函數能夠用於初始化夾具,可是測試函數可以覆寫它。請注意,覆寫測試樁函數是一種可能存在潛在問題的作法;
- 一旦測試樁函數被調用,該函數將會一致返回固定的值;
- 上一次調用測試樁函數有時候極爲重要-當你調用一個函數不少次時,最後一次調用多是你所感興趣的。
參數匹配器 (matchers)
3.Mockito以天然的java風格來驗證參數值: 使用equals()函數。有時,當須要額外的靈活性時你可能須要使用參數匹配器,也就是argument matchers :markdown
//stubbing using built-in anyInt() argument matcher
// 使用內置的anyInt()參數匹配器
when(mockedList.get(anyInt())).thenReturn("element");
//stubbing using custom matcher (let's say isValid() returns your own matcher implementation):
// 使用自定義的參數匹配器( 在isValid()函數中返回你本身的匹配器實現 )
when(mockedList.contains(argThat(isValid()))).thenReturn("element");
//following prints "element"
// 輸出element
System.out.println(mockedList.get(999));
//you can also verify using an argument matcher
// 你也能夠驗證參數匹配器
verify(mockedList).get(anyInt());
參數匹配器使驗證和測試樁變得更靈活。點擊這裏查看更多內置的匹配器以及自定義參數匹配器或者hamcrest 匹配器的示例。多線程
若是僅僅是獲取自定義參數匹配器的信息,查看ArgumentMatcher類文檔便可。
爲了合理的使用複雜的參數匹配,使用equals()與anyX() 的匹配器會使得測試代碼更簡潔、簡單。有時,會迫使你重構代碼以使用equals()匹配或者實現equals()函數來幫助你進行測試。
同時建議你閱讀第15章節或者ArgumentCaptor類文檔。ArgumentCaptor是一個可以捕獲參數值的特俗參數匹配器。
參數匹配器的注意點 :
若是你使用參數匹配器,全部參數都必須由匹配器提供。
示例 : ( 該示例展現瞭如何屢次應用於測試樁函數的驗證 )
verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
//above is correct - eq() is also an argument matcher
// 上述代碼是正確的,由於eq()也是一個參數匹配器
verify(mock).someMethod(anyInt(), anyString(), "third argument");
//above is incorrect - exception will be thrown because third argument
// 上述代碼是錯誤的,由於全部參數必須由匹配器提供,而參數"third argument"並不是由參數匹配器提供,所以的緣故會拋出異常
像anyObject(), eq()這樣的匹配器函數不會返回匹配器。它們會在內部將匹配器記錄到一個棧當中,而且返回一個假的值,一般爲null。這樣的實現是因爲被Java編譯器強加的靜態類型安全
。結果就是你不能在驗證或者測試樁函數以外使用anyObject(), eq()函數。
驗證函數的確切、最少、從未調用次數
4. //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默認驗證的就是times(1)
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)
// 使用never()進行驗證,never至關於times(0)
verify(mockedList, never()).add("never happened");
//verification using atLeast()/atMost()
// 使用atLeast()/atMost()
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("five times");
verify(mockedList, atMost(5)).add("three times");
verify函數默認驗證的是執行了times(1),也就是某個測試函數是否執行了1次.所以,times(1)一般被省略了。
爲返回值爲void的函數經過Stub拋出異常
5.doThrow(new RuntimeException()).when(mockedList).clear();
//following throws RuntimeException:
// 調用這句代碼會拋出異常
mockedList.clear();
關於doThrow|doAnswer 等函數族的信息請閱讀第十二章節。
最初,stubVoid(Object) 函數用於爲無返回值的函數打樁。如今stubVoid()函數已通過時,doThrow(Throwable)成爲了它的繼承者。這是爲了提高與 doAnswer(Answer) 函數族的可讀性與一致性。
驗證執行執行順序
6. // A. Single mock whose methods must be invoked in a particular order
// A. 驗證mock一個對象的函數執行順序
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
// 爲該mock對象建立一個inOrder對象
InOrder inOrder = inOrder(singleMock);
//following will make sure that add is first called with "was added first, then with "was added second"
// 確保add函數首先執行的是add("was added first"),而後纔是add("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
// B .驗證多個mock對象的函數執行順序
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
// 爲這兩個Mock對象建立inOrder對象
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
驗證執行順序是很是靈活的-你不須要一個一個的驗證全部交互,只須要驗證你感興趣的對象便可。 另外,你能夠僅經過那些須要驗證順序的mock對象來建立InOrder對象。
確保交互(interaction)操做不會執行在mock對象上
7. //using mocks - only mockOne is interacted
// 使用Mock對象
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
// 驗證mock對象沒有交互過
verifyZeroInteractions(mockTwo, mockThree);
查找冗餘的調用
8.//using mocks
mockedList.add("one");
mockedList.add("two");
verify(mockedList).add("one");
//following verification will fail
// 下面的驗證將會失敗
verifyNoMoreInteractions(mockedList);
一些用戶可能會在頻繁地使用verifyNoMoreInteractions()
,甚至在每一個測試函數中都用。可是verifyNoMoreInteractions()
並不建議在每一個測試函數中都使用。verifyNoMoreInteractions()
在交互測試套件中只是一個便利的驗證,它的做用是當你須要驗證是否存在冗餘調用時。濫用它將致使測試代碼的可維護性下降。你能夠閱讀這篇文檔來了解更多相關信息。
never()
是一種更爲明顯且易於理解的形式。
簡化mock對象的建立
9.- 最小化重複的建立代碼
- 使測試類的代碼可讀性更高
- 使驗證錯誤更易於閱讀,由於字段名可用於標識mock對象
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider;
private ArticleManager manager;
注意!下面這句代碼須要在運行測試函數以前被調用,通常放到測試類的基類或者test runner中:
MockitoAnnotations.initMocks(testClass);
你可使用內置的runner: MockitoJUnitRunner runner 或者一個rule : MockitoRule。 關於mock註解的更多信息能夠閱讀MockitoAnnotations文檔。
爲連續的調用作測試樁 (stub)
10.有時咱們須要爲同一個函數調用的不一樣的返回值或異常作測試樁。典型的運用就是使用mock迭代器。 原始版本的Mockito並無這個特性,例如,可使用Iterable或者簡單的集合來替換迭代器。這些方法提供了更天然的方式,在一些場景中爲連續的調用作測試樁會頗有用。示例以下 :
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
//First call: throws runtime exception:
// 第一次調用 : 拋出運行時異常
mock.someMethod("some arg");
//Second call: prints "foo"
// 第二次調用 : 輸出"foo"
System.out.println(mock.someMethod("some arg"));
//Any consecutive call: prints "foo" as well (last stubbing wins).
// 後續調用 : 也是輸出"foo"
System.out.println(mock.someMethod("some arg"));
另外,連續調用的另外一種更簡短的版本 :
// 第一次調用時返回"one",第二次返回"two",第三次返回"three"
when(mock.someMethod("some arg"))
.thenReturn("one", "two", "three");
爲回調作測試樁
11.Allows stubbing with generic Answer interface. 運行爲泛型接口Answer打樁。
在最初的Mockito裏也沒有這個具備爭議性的特性。咱們建議使用thenReturn() 或thenThrow()來打樁。這兩種方法足夠用於測試或者測試驅動開發。
when(mock.someMethod(anyString())).thenAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Object mock = invocation.getMock();
return "called with arguments: " + args;
}
});
//Following prints "called with arguments: foo"
// 輸出 : "called with arguments: foo"
System.out.println(mock.someMethod("foo"));
doReturn()、doThrow()、doAnswer()、doNothing()、doCallRealMethod()系列方法的運用
12.經過when(Object)
爲無返回值的函數打樁有不一樣的方法,由於編譯器不喜歡void函數在括號內...
使用doThrow(Throwable)
替換stubVoid(Object)
來爲void函數打樁是爲了與doAnswer()
等函數族保持一致性。
當你想爲void函數打樁時使用含有一個exception 參數的doAnswer()
:
doThrow(new RuntimeException()).when(mockedList).clear();
//following throws RuntimeException:
// 下面的代碼會拋出異常
mockedList.clear();
當你調用doThrow()
, doAnswer()
, doNothing()
, doReturn()
and doCallRealMethod()
這些函數時能夠在適當的位置調用when()
函數. 當你須要下面這些功能時這是必須的:
- 測試void函數
- 在受監控的對象上測試函數
- 不知一次的測試爲同一個函數,在測試過程當中改變mock對象的行爲。
可是在調用when()
函數時你能夠選擇是否調用這些上述這些函數。
閱讀更多關於這些方法的信息:
監控真實對象
13.你能夠爲真實對象建立一個監控(spy)對象。當你使用這個spy對象時真實的對象也會也調用,除非它的函數被stub了。儘可能少使用spy對象,使用時也須要當心形式,例如spy對象能夠用來處理遺留代碼。
監控一個真實的對象能夠與「局部mock對象」概念結合起來。在1.8以前,mockito的監控功能並非真正的局部mock對象。緣由是咱們認爲局部mock對象的實現方式並很差,在某些時候我發現一些使用局部mock對象的合法用例。(第三方接口、臨時重構遺留代碼,完整的文章在這裏 )
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對象調用真實對象的函數
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
// 由於size()函數被打樁了,所以這裏返回的是100
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)
// 不可能 : 由於當調用spy.get(0)時會調用真實對象的get(0)函數,此時會發生IndexOutOfBoundsException異常,由於真實List對象是空的
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
// 你須要使用doReturn()來打樁
doReturn("foo").when(spy).get(0);
Mockito並不會爲真實對象代理函數調用,實際上它會拷貝真實對象。所以若是你保留了真實對象而且與之交互,不要指望從監控對象獲得正確的結果。當你在監控對象上調用一個沒有被stub的函數時並不會調用真實對象的對應函數,你不會在真實對象上看到任何效果。
所以結論就是 : 當你在監控一個真實對象時,你想在stub這個真實對象的函數,那麼就是在自找麻煩。或者你根本不該該驗證這些函數。
修改沒有測試樁的調用的默認返回值 ( 1.7版本以後 )
14.你能夠指定策略來建立mock對象的返回值。這是一個高級特性,一般來講,你不須要寫這樣的測試。而後,它對於遺留系統來講是頗有用處的。當你不須要爲函數調用打樁時你能夠指定一個默認的answer。
Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
關於RETURNS_SMART_NULLS更多的信息請查看 : RETURNS_SMART_NULLS文檔 。
15. 爲下一步的斷言捕獲參數 (1.8版本以後)
Mockito以java代碼風格的形式來驗證參數值 : 即經過使用equals()
函數。這也是咱們推薦用於參數匹配的方式,由於這樣會使得測試代碼更簡單、簡潔。在某些狀況下,當驗證交互以後要檢測真實的參數值時這將變得有用。例如 :
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
// 參數捕獲
verify(mock).doSomething(argument.capture());
// 使用equal斷言
assertEquals("John", argument.getValue().getName());
警告 : 咱們建議使用沒有測試樁的ArgumentCaptor來驗證,由於使用含有測試樁的ArgumentCaptor會下降測試代碼的可讀性,由於captor是在斷言代碼塊以外建立的。另外一個好處是它能夠下降本地化的缺點,由於若是測試樁函數沒有被調用,那麼參數就不會被捕獲。總之,ArgumentCaptor與自定義的參數匹配器相關(能夠查看ArgumentMatcher類的文檔 )。這兩種技術都能用於檢測外部傳遞到Mock對象的參數。然而,使用ArgumentCaptor在如下的狀況下更合適 :
- 自定義不能被重用的參數匹配器
- 你僅須要斷言參數值
自定義參數匹配器相關的資料你能夠參考ArgumentMatcher文檔。
- 真實的局部mocks (1.8版本以後)
在內部經過郵件進行了無數爭辯和討論後,最終 Mockito 決定支持部分測試,早前咱們不支持是由於咱們認爲部分測試會讓代碼變得糟糕。然而,咱們發現了部分測試真正合理的用法。詳情點這
在 Mockito 1.8 以前,spy() 方法並不會產生真正的部分測試,而這無疑會讓一些開發者困惑。更詳細的內容能夠看:這裏 或 Java 文檔
//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 對象中,下降了抽象處理的複雜度。那部分測試是怎麼遵循這個規範的呢?事實上部分測試並無遵循這個規範……部分測試一般意味着抽象的複雜度被移動到同一個對象的不一樣方法中,在大多數狀況下,這不會是你想要的應用架構方式。
然而,在一些罕見的狀況下部分測試纔會是易用的:處理不能輕易修改的代碼(第三方接口,臨時重構的遺留代碼等等)。然而,爲了新的,測試驅動和架構優秀的代碼,我是不會使用部分測試的。
- 重置mocks對象 (1.8版本以後)
聰明的 Mockito 使用者不多會用到這個特性,由於他們知道這是出現糟糕測試單元的信號。一般狀況下你不會須要重設你的測試單元,只須要爲每個測試方法從新建立一個測試單元就能夠了。
若是你真的想經過 reset() 方法知足某些需求的話,請考慮實現簡單,小並且專一於測試方法而不是冗長,精確的測試。首先可能出現的代碼異味就是測試方法中間那的 reset() 方法。這可能意味着你已通過度測試了。請遵循測試方法的呢喃:請讓咱們小,並且專一於單一的行爲上。在 Mockito 郵件列表中就有好幾個討論是和這個有關的。
添加 reset() 方法的惟一緣由就是讓它能與容器注入的測試單元協做。詳情看 issue 55 或 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
- 故障排查與驗證框架的使用 (1.8版本以後)
首先,若是出現了任何問題,我建議你先看 Mockito FAQ。
任何你提的問題都會被提交到 Mockito 的郵件列表中。
而後你應該知道 Mockito 會驗證你是否始終以正確的方式使用它,對此有疑惑的話不妨看看 validateMockitoUsage() 的文檔說明。
19.行爲驅動開發的別名 (1.8版本以後)
行爲驅動開發實現測試單元的模式將 //given //when //then comments 視做測試方法的基礎,這也是咱們實現單元測試時被建議作的!
問題是當信息沒有很好地與 //given //when //then comments 交互時,扮演規範角色的測試樁 API 就會出現問題。這是由於測試樁屬於給定測試單元的組件,並且不是任何測試的組件。所以 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());
}
- 序列化mock對象
模擬對象能夠被序列化。有了這個特性你就能夠在依賴被序列化的狀況下使用模擬對象了。
警告:這個特性不多在單元測試中被使用。
To create serializable mock use MockSettings.serializable():
這個特性經過 BDD 擁有不可考外部依賴的特性的具體用例實現,來自外部依賴的 Web 環境和對象會被序列化,而後在不一樣層之間被傳遞。
List serializableMock = mock(List.class, withSettings().serializable());
The mock can be serialized assuming all the normal serialization requirements are met by the class.
模擬對象能被序列化假設全部普通的序列化要求都被類知足了。
讓一個真實的偵查對象可序列化須要多一些努力,由於 spy(...) 方法沒有接收 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版本以後)
V1.8.3 帶來的新註解在某些場景下可能會很實用
@Captor 簡化 ArgumentCaptor 的建立 - 當須要捕獲的參數是一個使人討厭的通用類,並且你想避免編譯時警告。
@Spy - 你能夠用它代替 spy(Object) 方法
@InjectMocks - 自動將模擬對象或偵查域注入到被測試對象中。須要注意的是 @InjectMocks 也能與 @Spy 一塊兒使用,這就意味着 Mockito 會注入模擬對象到測試的部分測試中。它的複雜度也是你應該使用部分測試緣由。
全部新的註解僅僅在 MockitoAnnotations.initMocks(Object) 方法中被處理,就像你在 built-in runner 中使用的 @Mock 註解:MockitoJUnitRunner 或 規範: MockitoRule.
- 驗證超時 (1.8.5版本以後)
容許帶有暫停的驗證。這使得一個驗證去等待一段特定的時間,以得到想要的交互而不是若是尚未發生事件就帶來的當即失敗。在併發條件下的測試這會頗有用。
感受起來這個特性應該不多被使用 - 指出更好的測試多線程系統的方法。
尚未實現去和 InOrder 驗證協做。
例子:
//passes when someMethod() is called within given time span
verify(mock, timeout(100)).someMethod();
//above is an alias to:
verify(mock, timeout(100).times(1)).someMethod();
//passes when someMethod() is called *exactly* 2 times within given time span
verify(mock, timeout(100).times(2)).someMethod();
//passes when someMethod() is called *at least* 2 times within given time span
verify(mock, timeout(100).atLeast(2)).someMethod();
//verifies someMethod() within given time span using given verification mode
//useful only if you have your own custom verification modes.
verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
- 自動初始化被@Spies, @InjectMocks註解的字段以及構造函數注入 (1.9.0版本以後)
Mockito 如今會經過注入構造方法、setter 或域注入儘量初始化帶有 @Spy 和 @InjectMocks 註解的域或方法。
爲了利用這一點特性,你須要使用 MockitoAnnotations.initMocks(Object), MockitoJUnitRunner 或 MockitoRule。
爲了 InjectMocks 請在 Java 文檔中瞭解更多可用的技巧和注入的規範
//instead:
@Spy BeerDrinker drinker = new BeerDrinker();
//you can write:
@Spy BeerDrinker drinker;
//same applies to @InjectMocks annotation:
@InjectMocks LocalPub;
- 單行測試樁 (1.9.0版本以後)
Mockito 如今容許你在使用測試樁時建立模擬對象。基本上,它容許在一行代碼中建立一個測試樁,這對保持代碼的整潔頗有用。舉例來講,有些乏味的測試樁會被建立,並在測試初始化域時被打入,例如:
public class CarTest {
Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();
@Test public void should... {}
- 驗證被忽略的測試樁 (1.9.0版本以後)
Mockito 如今容許爲了驗證無視測試樁。在與 verifyNoMoreInteractions() 方法或驗證 inOrder() 方法耦合時,有些時候會頗有用。幫助避免繁瑣的打入測試樁調用驗證 - 顯然咱們不會對驗證測試樁感興趣。
警告,ignoreStubs() 可能會致使 verifyNoMoreInteractions(ignoreStubs(...)) 的過分使用。謹記在心,Mockito 沒有推薦用 verifyNoMoreInteractions() 方法連續地施用於每個測試中,緣由在 Java 文檔中有。
一些例子:
verify(mock).foo();
verify(mockTwo).bar();
//ignores all stubbed methods:
verifyNoMoreInvocations(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();
更好的例子和更多的細節均可以在 Java 文檔的 ignoreStubs(Object...) 部分看到。
- mock詳情 (1.9.5版本以後)
爲了區別一個對象是模擬對象仍是偵查對象:
Mockito.mockingDetails(someObject).isMock();
Mockito.mockingDetails(someObject).isSpy();
MockingDetails.isMock() 和 MockingDetails.isSpy() 方法都會返回一個布爾值。由於一個偵查對象只是模擬對象的一種變種,因此 isMock() 方法在對象是偵查對象是會返回 true。在以後的 Mockito 版本中 MockingDetails 會變得更健壯,並提供其餘與模擬對象相關的有用信息,例如:調用,測試樁信息,等等……
###27. 委託調用真實實例 (Since 1.9.5)
當使用常規的 spy API 去 mock 或者 spy 一個對象很困難時能夠用 delegate 來 spy 或者 mock 對象的某一部分。 從 Mockito 的 1.10.11 版本開始, delegate 有可能和 mock 的類型相同也可能不一樣。若是不是同一類型, delegate 類型須要提供一個匹配方法不然就會拋出一個異常。下面是關於這個特性的一些用例:
- 帶有 interface 的 final 類
- 已經自定義代理的對象
- 帶有 finalize 方法的特殊對象,就是避免重複執行。
和常規 spy 的不一樣:
-
標準的 spy (spy(Object)) 包含被 spy 實例的全部狀態信息,方法在 spy 對象上被調用。被 spy 的對象只在 mock 建立時被用來拷貝狀態信息。若是你經過標準 spy 調用一個方法,這個 spy 會調用其內部的其餘方法記錄此次操做, 以便後面驗證使用。等效於存根 (stubbed)操做。
-
mock delegates 只是簡單的把全部方法委託給 delegate。delegate 一直被當成它代理的方法使用。若是你 從一個 mock 調用它被委託的方法,它會調用其內部方法,這些調用不會被記錄,stubbing 在這裏也不會生效。 Mock 的 delegates 相對於標準的 spy 來講功能弱了不少,不過在標準 spy 不能被建立的時候頗有用。
更多信息能夠看這裏 AdditionalAnswers.delegatesTo(Object).
###28. MockMaker API (Since 1.9.5)
爲了知足用戶的需求和 Android 平臺使用。Mockito 如今提供一個擴展點,容許替換代理生成引擎。默認狀況下,Mockito 使用 cglib 建立動態代理。
這個擴展點是爲想要擴展 Mockito 功能的高級用戶準備的。好比,咱們如今就能夠在 dexmaker 的幫助下使用 Mockito 測試 Android。
更多的細節,緣由和示例請看 MockMaker 的文檔。
###29. (new) BDD 風格的驗證 (Since 1.10.0)
開啓 Behavior Driven Development (BDD) 風格的驗證能夠經過 BBD 的關鍵詞 then 開始驗證。
given(dog.bark()).willReturn(2);
// when
...
then(person).should(times(2)).ride(bike);
更多信息請查閱 BDDMockito.then(Object) .
###30. (new) Spying 或 mocking 抽象類 (Since 1.10.12)
如今能夠方便的 spy 一個抽象類。注意,過分使用 spy 或許意味着代碼的設計上有問題。(see spy(Object)).
以前,spying 只能夠用在實例對象上。而如今新的 API 能夠在建立一個 mock 實例時使用構造函數。這對 mock 一個抽象類來講是很重要的,這樣使用者就沒必要再提供一個抽象類的實例了。目前的話只支持無參構造函數, 若是你認爲這樣還不夠的話歡迎向咱們反饋。
//convenience API, new overloaded spy() method:
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));
更多信息請見 MockSettings.useConstructor() .
###31. (new) Mockito mocks 能夠經過 classloaders 序列化/反序列化 (Since 1.10.0)
Mockito 經過 classloader 引入序列化。和其餘形式的序列化同樣,全部 mock 層的對象都要被序列化, 包括 answers。由於序列化模式須要大量的工做,因此這是一個可選擇設置。
// 常規的 serialization
mock(Book.class, withSettings().serializable());
// 經過 classloaders 序列化
mock(Book.class, withSettings().serializable(ACROSS_CLASSLOADERS));
更多信息請查看 MockSettings.serializable(SerializableMode).
###32. (new) Deep stubs 更好的泛型支持 (Since 1.10.0)
Deep stubbing 如今能夠更好的查找類的泛型信息。這就意味着像這樣的類 沒必要去 mock 它的行爲就可使用。
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 返回一個 mock 對象是錯誤的。
###33. (new) Mockito JUnit rule (Since 1.10.17)
Mockito 如今提供一個 JUnit rule。目前爲止,有兩種方法能夠初始化 fields ,使用 Mockito 提供的註解好比 @Mock, @Spy, @InjectMocks 等等。
- 用 @RunWith(@MockitoJUnitRunner.class) 標註 JUnit 測試類
- 在 @Before 以前調用 MockitoAnnotations.initMocks(Object)
如今你能夠選擇使用一個 rule:
@RunWith(YetAnotherRunner.class)
public class TheTest {
@Rule public MockitoRule mockito = MockitoJUnit.rule();
// ...
}
更多信息到這裏查看 MockitoJUnit.rule().
###34. (new) 開啓和關閉 plugins (Since 1.10.15)
這是一個測試特性,能夠控制一個 mockito-plugin 開啓或者關閉。詳情請查看 PluginSwitch
###35. 自定義驗證失敗信息 (Since 2.0.0)
容許聲明一個在驗證失敗時輸出的自定義消息 示例:
// will print a custom message on verification failure
verify(mock, description("This will print on failure")).someMethod();
// will work with any verification mode
verify(mock, times(2).description("someMethod should be called twice")).someMethod();
###字段摘要
類型 | 字段以及描述 |
static Answer< Object > | CALLS_REAL_METHODS 用於mock(Class, Answer)的可選參數Answer |
###字段詳情
**CALLS_REAL_METHODS** | |
public static final Answer CALLS_REAL_METHODS 用於mock(Class, Answer)的可選參數Answer Answer能夠用於定義unstubbed invocations的返回值. 這個Answer接口對於legacy code很是有用. 當使用這個接口的時候, unstubbed methods會被實現. 這是一種經過調用默認方法來建立partial mock對象的方式。 一般,你將要閱讀mock的部分警告:Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, , SRPy objects. partial mock是若是適應這種模式的呢?好吧!它不只僅是,partial mock一般意味着複雜性在同一個對象中移動到不一樣的方法.在大多數狀況下,這不是你想要的設計你的應用的方式。 然而,當partial mocks派上用場一樣也有少量狀況:處理你不易改變的代碼(第三方接口,legacy code的臨時重構).我將不使用partial mocks用於新的、測試驅動以及設計不錯的代碼。
|
###方法摘要
Modifier and Type | Method and Description |
static VerificationAfterDelay | after(long millis) 給定的時間後進行驗證 |
static VerificationMode | atLeast(int minNumberOfInvocations) 至少進行minNumberOfInvocations次驗證 |
static VerificationMode | atLeastOnce() 至少進行一次驗證 |
static VerificationMode | atMost(int maxNumberOfInvocations) 最多進行maxNumberOfInvocations次驗證 |
static VerificationMode | calls(int wantedNumberOfInvocations) 容許順序進行non-greedy驗證 |
#方法詳情 ##after
public static VerificationAfterDelay after(long millis)
在給定的時間後進行驗證。它會爲了預期的效果進行等待一段時間後進行驗證,而不是由於沒發生而當即失敗。這可能對於測試多併發條件很是有用。
after()等待整個週期的特色不一樣於timeout(),而timeout()一旦驗證經過就儘快中止,例如:當使用times(2)能夠產生不一樣的行爲方式,可能經過後過會又失敗。這種狀況下,timeout只要times(2)經過就會經過,而後after執行完整個週期時間,可能會失敗,也意味着times(2)也失敗。
感受這個方法應該少使用——找到更好的方法測試你的多線程系統。
對還沒有實現的工做進行驗證。
//passes after 100ms, if someMethod() has only been called once at that time.<br>
verify(mock, after(100)).someMethod();<br>
//above is an alias to:<br>
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<br>
verify(mock, after(100).never()).someMethod();
//verifies someMethod() after a given time span using given verification mode
//useful only if you have your own custom verification modes.
verify(mock, new After(100, yourOwnVerificationMode)).someMethod();
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
- millis - - time span in milliseconds
Returns:
- verification mode
##atLeast
public static VerificationMode atLeast(int minNumberOfInvocations)
容許至少進行x次驗證。例如:
verify(mock, atLeast(3)).someMethod("some arg");
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
- minNumberOfInvocations - invocations的最小次數
Returns:
- verification mode
##atLeastOnce
public static VerificationMode atLeastOnce()
至少進行一次一次驗證。例如:
verify(mock, atLeastOnce()).someMethod("some arg");
atLeast(1)的別名. 參照Mockito類的javadoc幫助文檔中的例子
Returns:
- verification mode
##atMost
public static VerificationMode atMost(int maxNumberOfInvocations)
至多進行x次驗證. 例如:
verify(mock, atMost(3)).someMethod("some arg");
參照Mockito類的javadoc幫助文檔中的例子
Parameters::
- maxNumberOfInvocations - invocations的最大次數
Returns:
- verification mode
##calls
public static VerificationMode calls(int wantedNumberOfInvocations)
容許順序進行non-greedy驗證. 例如:
inOrder.verify( mock, calls( 2 )).someMethod( "some arg" );
- 若是這個方法調用3次不會失敗,不一樣於times(2)
- 不會標記第三次驗證,不一樣於atLeast(2)
Parameters::
- wantedNumberOfInvocations - 驗證的次數
Returns:
- verification mode
#繼承org.mockito.Matchers的方法 ##any
public static <T> T any()<br><br>
匹配任何值,包括null
anyObject()的別名
參照Matchers類的javadoc幫助文檔中的例子
這是: anyObject() and any(java.lang.Class)的別名
Returns:
- null
##any
public static <T> T any(Class<T> clazz)
匹配任何對象,包括null
這個方法不進行給定參數的類型檢查,它就是爲了不代碼中的強制轉換(Casting)。然而這可能會改變(類型檢查能夠添加)未來的主要版本。
參照Matchers類的javadoc幫助文檔中的例子
這是: anyObject() and any(java.lang.Class)的別名
Returns:
- null
##anyBoolean
public static boolean anyBoolean()
任何boolean類型或非空(non-null)的Boolean.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- false
##anyByte
public static byte anyByte()
任何byte類型變量或非空(non-null)Byte.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 0
##anyChar
public static char anyChar()
任何char類型變量或非空(non-null)的Character.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 0
##anyCollection
public static Collection anyCollection()
任何非空(non-null)的Collection.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 空Collection.
##anyCollectionOf
public static < T > Collection < T > anyCollectionOf(Class<T> clazz)
通用友好的別名anyCollection()。爲了保持代碼清潔,經過@SuppressWarnings("unchecked")來進行替代編譯器警告。
任何非空(non-null)Collection.
這個方法不進行給定參數的類型檢查,它就是爲了不代碼中的強制轉換(Casting)。然而這可能會改變(類型檢查能夠添加)未來的主要版本。
參照Matchers類的javadoc幫助文檔中的例子
Parameters
- clazz - 類型屬於Collection類型避免類型轉換(Casting)
Returns:
- 空Collection.
##anyDouble
public static double anyDouble()
任何double類型或非空(non-null)的Double.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
##anyFloat
public static float anyFloat()
任何float類型或非空(non-null)Float.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
##anyInt
public static int anyInt()
任何int或非空(non-null)Integer.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
##anyList
public static List anyList()
任何非空(non-null)List.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 空List.
##anyListOf
public static < T > List < T > anyListOf(Class< T > clazz)
通用友好的別名anyList()。爲了保持代碼清潔,經過@SuppressWarnings("unchecked")來進行替代編譯器警告。
任何非空(non-null)List.
這個方法不進行給定參數的類型檢查,它就是爲了不代碼中的強制轉換(Casting)。然而這可能會改變(類型檢查能夠添加)未來的主要版本。
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
- clazz - 類型屬於List類型避免類型轉換(Casting)
Returns:
- 空List.
##anyLong
public static long anyLong()
任何long類型或非空(non-null)Long.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
##anyMap
public static Map anyMap()
任何非空(non-null)Map.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 空Map.
##anyMapOf
public static < K,V> Map < K,V> anyMapOf(Class< K> keyClazz, Class< V> valueClazz)
通用友好的別名anyMap()。爲了保持代碼清潔,經過@SuppressWarnings("unchecked")來進行替代編譯器警告。
任何非空(non-null)Map.
這個方法不進行給定參數的類型檢查,它就是爲了不代碼中的強制轉換(Casting)。然而這可能會改變(類型檢查能夠添加)未來的主要版本。
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
- keyClazz - map key類型避免類型強制轉換(Casting)
- valueClazz - value類型避免類型強制轉換(Casting)
Returns:
- 空Map.
##anyObject
public static < T> T anyObject()
匹配任何事物, 包含null.
這是: any()和any(java.lang.Class)的別名
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- empty null.
##anySet**
public static <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true">Set</a> anySet()
任何非空(non-null)Set.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 空Set.
##anySetOf
public static < T> Set < T> anySetOf(Class< T> clazz)
通用友好的別名anySet()。爲了保持代碼清潔,經過@SuppressWarnings("unchecked")來進行替代編譯器警告。
任何非空(non-null)Set.
這個方法不進行給定參數的類型檢查,它就是爲了不代碼中的強制轉換(Casting)。然而這可能會改變(類型檢查能夠添加)未來的主要版本。
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
- clazz - 類型屬於Set爲了不類型強制轉換(Casting)
Returns:
- 空Set.
##anyShort
public static short anyShort()
任何short類型或非空(non-null)Short.
參照Matchers類的javadoc幫助文檔中的例子
Returns:
##anyString
public static String anyString()
任何非空(non-null)String
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- 空String ("").
##anyVararg
public static < T> T anyVararg()
任何vararg類型, 即任何參數(arguments)的number和values
例如:
//verification:
mock.foo(1, 2);
mock.foo(1, 2, 3, 4);
verify(mock, times(2)).foo(anyVararg());
//stubbing:
when(mock.foo(anyVararg()).thenReturn(100);
//prints 100
System.out.println(mock.foo(1, 2));
//also prints 100<
System.out.println(mock.foo(1, 2, 3, 4));
參照Matchers類的javadoc幫助文檔中的例子
Returns:
- null.
##argThat
public static < T> T argThat(ArgumentMatcher < T> matcher)
容許建立自定義的參數匹配模式.這個API在2.0中已經改變,請閱讀ArgumentMatcher基礎指南。
在實現自定義參數匹配模式前,理解使用的場景和non-trivial參數的可用選項是很是重要的。這種方式下,你能夠在給定的狀況下選擇最好的方法來設計製造高質量的測試(清潔和維護).請閱讀ArgumentMatcher文檔學習方法和例子。
在極少數狀況下,當參數是基本數據類型(primitive)時,你必須使用相關的intThat()、floatThat()等方法。這些方法在進行自動拆箱(auto-unboxing)時能夠避免NullPointerException異常。
參照ArgumentMatcher類的javadoc幫助文檔中的例子
Parameters:
- matcher - 取決於選擇的參數匹配模式(argument matches)
Returns:
- null.
##booleanThat
public static boolean booleanThat(ArgumentMatcher < Boolean> matcher)
容許建立自定義的Boolean類型參數匹配模式(Boolean argument matchers).
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
-
matcher - 取決於選擇的參數匹配模式(argument matches) Returns:
-
false.
##byteThat
public static byte byteThat(ArgumentMatcher < Byte> matcher)
容許建立自定義的Byte類型參數匹配模式(Byte argument matchers)
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
- matcher - 取決於選擇的參數匹配模式(argument matches)
Returns:
##charThat
public static char charThat(ArgumentMatcher < Character> matcher)
容許建立自定義的Character類型參數匹配模式(Character argument matchers)
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
- matcher - 取決於選擇的參數匹配模式(argument matches)
Returns:
contains
public static String contains(String substring)
String參數包含給定的substring字符串.
參照Matchers類的javadoc幫助文檔中的例子
Parameters:
- substring - substring字符串.
Returns:
- 空String ("").
##description函數
public static VerificationMod description(String description)
添加驗證失敗時要輸出的文字內容
verify(mock, description("This will print on failure")).someMethod("some arg");
Parameters:
輸出的文字內容
Returns:
驗證模式
Since:
- 2.0.0
##doAnswer函數
public static Stubber doAnswer(Answer answer)
當你想要測試一個無返回值的函數時,可使用一個含有泛型類Answer參數的doAnswer()函數。爲無返回值的函數作測試樁與when(Objecy)
方法不一樣,由於編譯器不喜歡在大括號內使用void函數。
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Mock mock = invocation.getMock();
return null;
}})
.when(mock).someMethod();
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
測試函數的應答內容
Returns:
測試方法的測試樁
##doCallRealMethod函數
public static Stubber doCallRealMethod()
若是你想調用某一個方法的真實實現請使用doCallRealMethod()
。
像往常同樣你須要閱讀局部的mock對象警告:面向對象編程經過將複雜的事物分解成單獨的、具體的、SRPY對象來減小對復瑣事件的處理。 局部模擬是如何符合這種範式的呢。?局部模擬一般狀況下是指在對象相同的狀況下那些複雜的事物被移動另外一個不一樣的方法中。在大多數狀況下,並無按照你所但願的方式來設計你的應用。
然而,使用局部mock對象也會有個別狀況:有些代碼你並不能很是容易的改變(3rd接口,臨時遺留代碼的重構等),可是我對於新的、測試驅動及良好設計的代碼不會使用局部mock對象。
一樣在javadoc中spy(Object)
閱讀更多關於partial mocks的說明.推薦使用Mockito.spy()
來建立局部mock對象緣由是因爲你負責構建對象並傳值到spy()
中,它只管保證被調用。
Foo mock = mock(Foo.class);
doCallRealMethod().when(mock).someVoidMethod();
// this will call the real implementation of Foo.someVoidMethod()
// 調用Foo.someVoidMethod()的真實現
mock.someVoidMethod();
參照Mockito類的javadoc幫助文檔中的例子
Returns:
測試方法的測試樁
Since:
- 1.9.5
##doNothing函數
public static Stubber doNothing()
使用doNothing()
函數是爲了設置void函數什麼也不作。須要注意的是默認狀況下返回值爲void的函數在mocks中是什麼也不作的可是,也會有一些特殊狀況。
1.測試樁連續調用一個void函數
doNothing().
doThrow(new RuntimeException())
.when(mock).someVoidMethod();
//does nothing the first time:
//第一次才能都沒作
mock.someVoidMethod();
//throws RuntimeException the next time:
//一下次拋出RuntimeException
mock.someVoidMethod();
2.當你監控真實的對象而且你想讓void函數什麼也不作:
List list = new LinkedList();
List spy = spy(list);
//let's make clear() do nothing
doNothing().when(spy).clear();
spy.add("one");
//clear() does nothing, so the list still contains "one"
spy.clear();
參照Mockito類的javadoc幫助文檔中的例子
Returns:
stubber - 測試方法的測試樁
##doReturn函數
public static Stubber doReturn(Object toBeReturned)
在某些特殊狀況下若是你沒法使用when(Object)
可使用doReturn()
函數
注意:對於測試樁推薦使用when(Object)
函數,由於它是類型安全的而且可讀性更強(特別是在測試樁連續調用的狀況下)
都有哪些特殊狀況下須要使用doReturn()
1.當監控真實的對象而且調用真實的函數帶來的影響時:
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
// 不能完成的:真實方法被調用因此spy.get(0)拋出IndexOutOfBoundsException(list還是空的)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing:
//你應用使用doReturn()函數
doReturn("foo").when(spy).get(0);
- 重寫一個前exception-stubbing:
when(mock.foo()).thenThrow(new RuntimeException());
//Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
// 不能完成的:exception-stubbed foo()被調用拋出RuntimeException異常
when(mock.foo()).thenReturn("bar");
//You have to use doReturn() for stubbing:
//你應用使用doReturn()函數
doReturn("bar").when(mock).foo();
上面的狀況展現了Mockito's的優雅語法。注意這些狀況並不常見。監控應該是分散的而且重寫exception-stubbing也不常見。更況且對於指出測試樁並複寫測試樁是一種潛在的代碼嗅覺
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
toBeReturned - 當測試樁函數被調用時要被返回的對象
Returns:
stubber - 測試方法的測試樁
##doThrow函數
public static Stubber doThrow(Class<? extends Throwable> toBeThrown)
當你想測試void函數中指定類的拋出異常時使用doThrow()
當每個函數被調用時一個新的異常實例將會被建立
爲無返回值的函數作測試樁與when(Objecy)
方法不一樣,由於編譯器不喜歡在大括號內使用void函數。
doThrow(RuntimeException.class).when(mock).someVoidMethod();
Parameters:
測試方法被調用時返回的對象
Returns:
測試方法的測試樁
Since:
- 1.9.0
##doThrow函數
public static Stubber doThrow(Throwable toBeThrown)
當測試一個void函數的異常時使用doThrow()
測試void函數須要與使用when(Object)
不一樣的方式,由於編譯器不喜歡大括號內有void函數
Example:
doThrow(RuntimeException.class).when(mock).someVoidMethod();
Parameters:
測試方法被調用時返回的對象
Returns:
測試方法的測試樁
Since:
- 1.9.0
##ignoreStubs函數
public static Object[] ignoreStubs(Object... mocks)
忽略對驗證函數的測試,當與verifyNoMoreInteractions()
成對出現或是驗證inOrder()時是頗有用的。避免了在測試時的多餘驗證,實際上咱們對驗證測試一點也不感興趣。
警告,ignoreStubs()
可能會致使verifyNoMoreInteractions(ignoreStubs(...))
的過分使用。考慮到Mockito並不推薦使用verifyNoMoreInteractions()
函數轟炸每個測試,這其中的起因在文檔verifyNoMoreInteractions(Object…)
部分已經說明:換句話說在mocks中全部* stubbed * 的函數都被標記爲 * verified * 因此不須要使用這種方式。
該方法改變了input mocks!該方法只是爲了方便返回 imput mocks 。
忽略測試也會被忽略掉驗證inOrder,包括InOrder.verifyNoMoreInteractions()
,看下面第二個示例:
Example:
//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:
// 調用stubbed get(0)使用mocks
System.out.println(mock1.get(0)); //prints 10
System.out.println(mock2.get(0)); //prints 20
//using mocks by calling clear() methods:
// 調用clear()使用mocks
mock1.clear();
mock2.clear();
//verification:
// 驗證
verify(mock1).clear();
verify(mock2).clear();
//verifyNoMoreInteractions() fails because get() methods were not accounted for.
// verifyNoMoreInteractions()會失敗,由於get()未關聯帳號
try { verifyNoMoreInteractions(mock1, mock2); } catch (NoInteractionsWanted e);
//However, if we ignore stubbed methods then we can verifyNoMoreInteractions()
//如要咱們忽略測試函數我能夠這樣verifyNoMoreInteractions()
verifyNoMoreInteractions(ignoreStubs(mock1, mock2));
//Remember that ignoreStubs() *changes* the input mocks and returns them for convenience.
忽略測試能夠用於verification in order:
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();
Parameters:
將被改變的input mocks
Returns:
和傳入參數同樣的mocks
Since:
1.9.0
##inOrder函數
public static InOrder inOrder(Object... mocks)
建立InOrder對象驗證 mocks in order
InOrder inOrder = inOrder(firstMock, secondMock);
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
驗證in order是很靈活的。你能夠只驗證你感興趣的,並不須要一個一個驗證全部的交互。一樣你也能夠建立InOrder對象只在相關in-order的驗證中進行傳值。
InOrder
驗證是'greedy'.你很難每個都注意到。你能夠在Mockito wiki pages頁搜索'greedy'獲取更多信息。
Mockito 1.8.4版本你能以order-sensitive方式調用verifyNoMoreInvocations()
,閱讀更多InOrder.verifyNoMoreInteractions()
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
in order中被修改的mocks
Returns:
in order中被用於驗證的InOrder對象
##mock函數
public static <T> T mock(Class <T> classToMock)
對給定的類或接口建立mock對象
Parameters:
須要mock的類或接口
Returns:
mock對象
##mock函數
public static <T> T mock(Class <T> classToMock, Answer defaultAnswer)
根據它對交互的迴應指明策略建立mock對象。這個是比較高級特性而且你不須要它寫多少測試代碼。可是對於legacy系統這是很是有用的。
這個是默認answer,因此當你不想測試函數時你可使用它。
Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
-
須要mock的類或接口
-
未測試函數的默認answer
Returns:
mock對象
##mock函數
public static <T> T mock(Class <T> classToMock, MockSettings mockSettings)
沒有標準的設置來建立mock對象
配置點的數目對mock的擴大有影響,因此咱們在沒有愈來愈多重載Mockito.mock()的狀況下須要一種更流利的方式來介紹一種新的配置方式。即MockSettings.
Listener mock = mock(Listener.class, withSettings()
.name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
);
使用它時須要當心一些而且不要經常使用。在什麼狀況下你的測試會不須要標準配置的mocks?在測試代碼下太複雜以致於不須要標準配置的mocks?你有沒有重構測試代碼來讓它更加容易測試?
也能夠參考withSettings()
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
- 須要mock的類或接口
- mock配置
Returns:
- mock對象
##mock
@Deprecated
@已過時
public static <T> T mock(Class <T> classToMock, ReturnValues returnValues)
已過時,請使用mock(Foo.class, defaultAnswer)
;
已過時,請使用mock(Foo.class, defaultAnswer)
;
爲何會過時?爲了框架更好的一致性與交互性用Answer替換了ReturnValues。Answer接口很早就存在框架中了而且它有和ReturnValues同樣的責任。沒有必要維護兩個同樣的接口。
針對它的返回值須要指明策略來建立mock對象。這個是比較高級特性而且你不須要它寫多少測試代碼。可是對於legacy系統這是很是有用的。
明顯地,當你不須要測試方法時可使用這個返回值。
Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
Foo mockTwo = mock(Foo.class, new YourOwnReturnValues());
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
- 須要mock的類或接口
- 未測試方法默認返回值
Returns:
- mock對象
##mock
public static <T> T mock(Class <T> classToMock, String name)
指明mock的名字。命名mock在debug的時候很是有用。名字會在全部驗證錯誤中使用。須要注意的是對於使用太多mock或者collaborators的複雜代碼命名mock並不能解決問題。若是你使用了太多的mock,爲了更加容易測試/調試 你須要對其進行重構而不是對mock命名。
若是你使用了@Mock註解,意味着你的mock已經有名字了!
@Mock使用字段名稱做爲mock名字Read more
參照Mockito類的javadoc幫助文檔中的例子
Parameters:
- 須要mock的類或接口
- mock的名字
Returns:
- mock對象
mockingDetails函數
public static MockingDetails mockingDetails(Object toInspect)
對於Mockito的關聯信息返回MockingDetails實例能夠用於檢查某一特定的對象,不管給定的對象是mock仍是監視的均可以被找出來。
在Mockito之後的版本中MockingDetails可能會擴大而且提供其它有用的有關mock的信息。e.g. invocations, stubbing info, etc.
Parameters:
- 要檢查的對象。容許爲空
Returns:
Since:
- 1.9.5
n-w開頭的函數
never()函數
public static VerificationMode never()
至關於times(0)
,可參見 times(int)
驗證交互沒有發生. 例如:
verify(mock, never()).someMethod();
若是你想驗證mock
之間沒有交互,可使用verifyZeroInteractions(Object...)
或者 verifyNoMoreInteractions(Object...)
這兩個方法
具體例子能夠參考Javadoc
中的Mockito
類
Returns:
- 驗證模式
only()函數
public static VerificationMode only()
若是當前mock
的方法只被調用一次,則容許被檢驗。例如:
verify(mock, only()).someMethod();
//上面這行代碼是下面這兩行代碼的簡寫
verify(mock).someMethod();
verifyNoMoreInvocations(mock);
能夠參考verifyNoMoreInteractions(Object...)
方法
具體例子能夠參考Javadoc
中的Mockito
類
Returns:
- verification mode
reset(T... mocks)函數
public static <T> void reset(T... mocks)
聰明的程序員不多會使用這個方法,由於他們知道使用這個方法意味着這個測試寫的很low.一般狀況下,你不須要重置你的mocks
,你僅僅須要爲你的測試方法建立新的mocks
就能夠了。
你能夠考慮寫一些簡單的、精悍的、聚焦的測試方法來代替reset()
這個方法。當你在在測試方法的中間部分用到reset()這個方法時,說明你的測試方法太龐大了。
請遵循如下關於測試方法的建議:請保證你的測試方法在一個動做中短小、精悍、聚焦
。在mockito
的郵件列表中有不少關於這方面的主題討論。
咱們添加reset()
方法的惟一緣由是使得注入容器的mocks
得以有效的運行,具體能夠參看issue 55 here or FAQ here
不要敗壞了你在程序員界的名聲,測試方法中間的reset()
方法是代碼中的害羣之馬(這意味着你的這個測試方法太多)
List mock = mock(List.class);
when(mock.size()).thenReturn(10);
mock.add(1);
reset(mock);
//此時會清除你以前全部的交互以及測試樁
Type Parameters:
- T - mocks的類型
Parameters:
- 被重置的mocks
spy(Class classToSpy)函數
@Incubating public static <T> T spy(Class<T> classToSpy)
請參考關於類spy
的文檔,過渡使用spy
會致使代碼變的很是糟糕。
相比與原來的spy
(對象),這種方法能夠在類的基礎上建立一個spy
,而不是一個對象。有時你能夠很方便基於類建立spy而避免提供一個spy
對象的實例。
由於他們不能被實例化,因此這個對於抽象類的監控很是有用。參見mocksettings.useconstructor()
。
例如:
SomeAbstract spy = spy(SomeAbstract.class);
//Robust API, via settings builder:
//穩定的API,充過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));
Type Parameters:
- T - spy的類型
Parameters:
- spy的類
Returns:
- a spy of the provided class
Since:
- 1.10.12
stub(T methodCall)函數
public static <T> DeprecatedOngoingStubbing<T> stub(T methodCall)
對一個方法打樁會返回結果值或者錯誤異常,例如:
stub(mock.someMethod()).toReturn(10);
//you can use flexible argument matchers, e.g:
//你可使用靈活的參數匹配,例如:
stub(mock.someMethod(anyString())).toReturn(10);
//setting exception to be thrown:
//設置拋出的異常
stub(mock.someMethod("some arg")).toThrow(new RuntimeException());
//you can stub with different behavior for consecutive method calls.
// 你能夠對不一樣做用的連續回調的方法打測試樁:
//Last stubbing (e.g: toReturn("foo")) determines the behavior for further consecutive calls.
// 最後面的測試樁(例如:返回一個對象:"foo")決定了接下來的回調方法以及它的行爲。
stub(mock.someMethod("some arg"))
.toThrow(new RuntimeException())
.toReturn("foo");
一些用戶有點混亂、混淆,是由於相比於'stub()','when(Object)'更加被推薦
//Instead of: //替代爲: stub(mock.count()).toReturn(10); //你能夠這樣作: //You can do: when(mock.count()).thenReturn(10);
當對一個返回值爲空且拋出異常的方法打測試樁:doThrow(Throwable)
測試樁會被重寫:例如一般測試樁會設置爲經常使用固定設置,但測試方法能夠重寫它。切記重寫測試樁是一種很是不推薦的寫法,由於這樣作會致使很是多的測試樁。
一旦這個方法打過樁,不管這個方法被調用多少次,這個方法會一直返回這個測試樁的值。
當你對相同的方法調用相同的參數打測試樁不少次,最後面的測試樁則很是重要
儘管咱們能夠去驗證對測試樁的調用,但一般它都是多餘的。好比說你對foo.bar()
打測試樁。若是你比較關心的是當某些狀況foo.bar()
中斷了(常常在verify()
方法執行以前),此時會返回什麼。若是你的代碼不關心是get(0)
會返回什麼那麼它就不該該被添加測試樁。若是你還不肯定?看這裏
Parameters:
- methodCall - 調用的方法
Returns:
- DeprecatedOngoingStubbing 對象是用來設置測試樁的值或者異常的
stubVoid(T mock)函數
public static <T> VoidMethodStubbable<T> stubVoid(T mock)
已廢棄.使用doThrow(Throwable)
方法代替去打空測試樁
//Instead of: //替代爲: stubVoid(mock).toThrow(e).on().someVoidMethod(); //Please do: //請這樣作: doThrow(e).when(mock).someVoidMethod();
doThrow()
之因此取代了stubVoid()
方法,是由於它增長了和它的兄弟方法doAnswer()
的可讀性以及一致性
stubVoid(mock).toThrow(new RuntimeException()).on().someMethod(); //you can stub with different behavior for consecutive calls. //你能夠對不一樣做用的連續回調的方法打測試樁: //Last stubbing (e.g. toReturn()) determines the behavior for further consecutive calls. //最後面的測試樁(例如:`toReturn()`)決定了接下來的回調方法以及它的行爲。 stubVoid(mock) .toThrow(new RuntimeException()) .toReturn() .on().someMethod();
具體例子能夠參考Javadoc
中的Mockito
類
Parameters:
- mock - to stub
Returns:
- stubbable object that allows stubbing with throwable
timesout(long millis)函數
public static VerificationWithTimeout timeout(long millis)
容許驗證時使用timeout
。它會在指定的時間後觸發你所指望的動做,而不是當即失敗,也許這個對併發條件下的測試很是有用。它和after()
是有全部不一樣的,由於after()
會等候一個完整的時期,除非最終的測試結果很快就出來了(例如:當never()
失敗了), 然而當驗證經過時,timeout()
會快速地中止,當你使用times(2)
時會產生不一樣的行爲。例如,當先經過而後失敗,在這種狀況下,timeout
將會當time(2)
經過時迅速經過,然而after()
將會一直運行直到times(2)
失敗,而後它也一同失敗。
這個功能看起來應該極少使用,但在多線程的系統的測試中,這是一個很好的方式
目前還沒有實現按照順序去驗證
//passes when someMethod() is called within given time span //當`someMethod()`被以時間段的形式調用時經過 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 // 在超時以前,`someMethod()`經過了2次調用 verify(mock, timeout(100).times(2)).someMethod(); //equivalent: this also passes as soon as someMethod() has been called 2 times before the given timeout //這個和上面的寫法是等價的,也是在超時以前,`someMethod()`經過了2次調用 verify(mock, timeout(100).atLeast(2)).someMethod(); //verifies someMethod() within given time span using given verification mode //在一個超時時間段內,用自定義的驗證模式去驗證`someMethod()`方法 //useful only if you have your own custom verification modes. //只有在你有本身定製的驗證模式時纔有用 verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
具體例子能夠參考Javadoc
中的Mockito
類
Parameters:
- millis - - 時間長度(單位:毫秒)
Returns:
- 驗證模式
time(int wantedNumberOfInvocations)函數
public static VerificationMode times(int wantedNumberOfInvocations)
容許驗證調用方法的精確次數,例如:
verify(mock, times(2)).someMethod("some arg"); //連續調用該方法兩次
具體例子能夠參考Javadoc
中的Mockito
類
Parameters:
- wantedNumberOfInvocations - 但願調用的次數
Returns:
- 驗證模式
validateMockitoUsage()函數
public static void validateMockitoUsage()
首頁,不管遇到任何問題,我都鼓勵你去閱讀the Mockito
問答集:http://groups.google.com/group/mockito,你也能夠在mockito
郵件列表提問http://groups.google.com/group/mockito.
validateMockitoUsage()
會明確地檢驗framework
的狀態以用來檢查Mockito
是否有效使用。可是,這個功能是可選的,由於**'Mockito`會使這個用法一直有效**,不過有一個問題請繼續讀下去。
錯誤示例:
//Oops, thenReturn() part is missing: //小心,`thenReturn()`部分是缺失的 when(mock.get()); //Oops, verified method call is inside verify() where it should be on the outside: //小心,下面驗證方法的調用在`verify()`裏面,其實應該在外面 verify(mock.execute()); //Oops, missing method to verify: //小心,驗證缺失方法 verify(mock);
若是你錯誤的使用了Mockito
,這樣將會拋出異常,這樣你就會知道你的測試是否寫的正確。你要清楚當你使用這個框架時,Mockito
會接下來的全部時刻開始驗證(例如:下一次你驗證、打測試樁、調用mock
等)。儘管在下一次測試中可能會拋出異常,但這個異常消息包含了一個完整棧蹤影路徑以及這個錯誤的位置。此時你能夠點擊並找到這個Mockito
使用錯誤的地方。
有時,你可能想知道這個框架的使用方法。好比,一個用戶想將validateMockitoUsage()
放在它的@after
方法中,爲了能快速地知道它使用Mockito
時哪裏錯了。若是沒有這個,它使用這個框架時將不能那麼迅速地知道哪裏使用錯了。另外在@after
中使用validateMockitoUsage()
比較好的一點是jUnit runner
以及Junit rule
中的測試方法在有錯誤時也會失敗,然而普通的next-time
驗證可能會在下一次測試方法中才失敗。可是儘管Junit
可能對下一次測試報告顯示紅色,但不要擔憂,這個異常消息包含了一個完整棧蹤影路徑以及這個錯誤的位置。此時你能夠點擊並找到這個Mockito
使用錯誤的地方。
一樣在runner中:MockitoJUnitRunner and rule
:MockitoRule
在每次測試方法以後運行validateMockitoUsage()
必定要牢記一般你不須要'validateMockitoUsage()'和框架驗證,由於基於next-time
觸發的應該已經足夠,主要是由於能夠點擊出錯位置查看強大的錯誤異常消息。可是,若是你已經有足夠的測試基礎(好比你爲全部的測試寫有本身的runner
或者基類),我將會推薦你使用validateMockitoUsage()
,由於對@After
添加一個特別的功能時將是零成本。
具體例子能夠參考Javadoc
中的Mockito
類
verify(T mock)函數
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
類
Parameters:
-
mock - 要被驗證的 Returns:
-
mock自己
verifyNoMoreInteractions(Object... mocks)函數
public static void verifyNoMoreInteractions(Object... mocks)
檢查入參的mocks
是否有任何未經驗證的交互,你能夠在驗證你的mocks
以後使用這個方法,用以確保你的mocks
沒有其它地方會被調用.
測試柱的調用也被當作是交互。
**警告:**一些使用者,傾向於常用verifyNoMoreInteractions()
方法作大量經典的、指望-運行-驗證的模擬,甚至是在全部的測試方法中使用。verifyNoMoreInteractions()
並不被推薦於使用在全部的測試方法中。在交互測試工具中,verifyNoMoreInteractions()
是一個很方便的斷言。你只能在當它是明確的、相關的時候使用它。濫用它將致使多餘的指定、不可維護的測試。你能夠在這裏查找更多的文章。
這個方法會在測試方法運行以前檢查未經驗證的調用,例如:在setUp()
,@Before
方法或者構造函數中。考慮到要寫出良好優秀的代碼,交互只可以在測試方法中。
示例:
//interactions
//交互
mock.doSomething();
mock.doSomethingUnexpected();
//verification
//驗證
verify(mock).doSomething();
//following will fail because 'doSomethingUnexpected()' is unexpected
//由於'doSomethingUnexpected()'是未被指望的,因此下面將會失敗
verifyNoMoreInteractions(mock);
具體例子能夠參考Javadoc
中的Mockito
類
Parameters:
- mocks - 被驗證的
verifyZeroInteractions(Object... mocks)函數
public static void verifyZeroInteractions(Object... mocks)
傳進來的mocks之間沒有任何交互。
verifyZeroInteractions(mockOne, mockTwo);
這個方法會在測試方法運行以前檢查調用,例如:在setUp()
,@Before
方法或者構造函數中。考慮到要寫出良好的代碼,交互只可以在測試方法中。
你也能夠參考never()方法 - 這個方法很明確的表達了當前方法的用途. 具體例子能夠參考Javadoc
中的Mockito
類
Parameters:
- mocks - 被驗證的
when(T methodCall)函數
public static <T> OngoingStubbing<T> when(T methodCall)
使測試樁方法生效。當你想讓這個mock
能調用特定的方法返回特定的值,那麼你就可使用它。 簡而言之:當你調用x
方法時會返回y
。
when()
是繼承自已經廢棄的方法stub(Object)
例如:
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.
//最後面的測試樁(例如:返回一個對象:"foo")決定了接下來的回調方法以及它的行爲。
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
//Alternative, shorter version for consecutive stubbing:
//能夠用如下方式替代,比較小版本的連貫測試樁:
when(mock.someMethod("some arg"))
.thenReturn("one", "two");
//is the same as:
//和下面的方式效果是同樣的
when(mock.someMethod("some arg"))
.thenReturn("one")
.thenReturn("two");
//shorter version for consecutive method calls throwing exceptions:
//比較小版本的連貫測試樁而且拋出異常:
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException(), new NullPointerException();
當你打空方法的測試樁,相關異常可參見:doThrow(Throwable)
,Stubbing
能夠被重寫:好比:普通的測試樁可使用固定的設置,可是測試方法可以重寫它。切記重寫測試樁是一種很是不推薦的寫法,由於這樣作會致使很是多的測試樁。
一旦這個方法打過樁,不管這個方法被調用多少次,這個方法會一直返回這個測試樁的值。
當你對相同的方法調用相同的參數打測試樁不少次,最後面的測試樁則很是重要
儘管咱們能夠去驗證對測試樁的調用,但一般它都是多餘的。好比說你對foo.bar()
打測試樁。若是你比較關心的是當某些狀況foo.bar()
中斷了(常常在verify()
方法執行以前),此時會返回什麼。若是你的代碼不關心是get(0)
會返回什麼那麼它就不該該被添加測試樁。若是你還不肯定?看這裏
具體例子能夠參考Javadoc
中的Mockito
類
Parameters:
- methodCall - 調用的方法
Returns:
- 一般是
OngoingStubbing
對象。不要爲被返回的對象建立一個引用。
withSettings()函數
public static MockSettings withSettings()
能夠在建立mock
時添加設置。 不要常常去設置它。應該在使用簡單的mocks
時寫簡單的設置。跟着我重複:簡單的測試會使總體的代碼更簡單,更可讀、更可維護。若是你不能把測試寫的很簡單-那麼請在測試時重構你的代碼。
mock
設置的例子
//Creates mock with different default answer & name
//用不一樣的默認結果和名字去建立`mock`
Foo mock = mock(Foo.class, withSettings()
.defaultAnswer(RETURNS_SMART_NULLS)
.name("cool mockie"));
//Creates mock with different default answer, descriptive name and extra interfaces
////用不一樣的默認結果和描述的名稱以及額外的接口去建立`mock`
Foo mock = mock(Foo.class, withSettings()
.defaultAnswer(RETURNS_SMART_NULLS)
.name("cool mockie")
.extraInterfaces(Bar.class));
有兩種緣由推薦使用MockSettings
.第一種,有需求要增長另一種mock
設置,這樣用起來更方便。第二種,可以結合不一樣的moke
設置以減小大量重載moke()
方法。
具體可參考MockSettings
文檔來學習mock settins
Returns:
mock settings
默認實例