欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java測(cè)試框架Mockito的簡(jiǎn)明教程

 更新時(shí)間:2019年06月13日 15:21:58   作者:Way Lau  
這篇文章主要介紹了Java測(cè)試框架Mockito的簡(jiǎn)明教程,Mock 測(cè)試是單元測(cè)試的重要方法之一。本文介紹了基于 Java 語(yǔ)言的 Mock 測(cè)試框架 – Mockito 的使用。,需要的朋友可以參考下

什么是 Mock 測(cè)試

Mock 測(cè)試就是在測(cè)試過(guò)程中,對(duì)于某些不容易構(gòu)造(如 HttpServletRequest 必須在Servlet 容器中才能構(gòu)造出來(lái))或者不容易獲取比較復(fù)雜的對(duì)象(如 JDBC 中的ResultSet 對(duì)象),用一個(gè)虛擬的對(duì)象(Mock 對(duì)象)來(lái)創(chuàng)建以便測(cè)試的測(cè)試方法。

Mock 最大的功能是幫你把單元測(cè)試的耦合分解開(kāi),如果你的代碼對(duì)另一個(gè)類(lèi)或者接口有依賴(lài),它能夠幫你模擬這些依賴(lài),并幫你驗(yàn)證所調(diào)用的依賴(lài)的行為。

比如一段代碼有這樣的依賴(lài):

當(dāng)我們需要測(cè)試A類(lèi)的時(shí)候,如果沒(méi)有 Mock,則我們需要把整個(gè)依賴(lài)樹(shù)都構(gòu)建出來(lái),而使用 Mock 的話就可以將結(jié)構(gòu)分解開(kāi),像下面這樣:

Mock 對(duì)象使用范疇

真實(shí)對(duì)象具有不可確定的行為,產(chǎn)生不可預(yù)測(cè)的效果(如:股票行情,天氣預(yù)報(bào)) :

  • 真實(shí)對(duì)象很難被創(chuàng)建的
  • 真實(shí)對(duì)象的某些行為很難被觸發(fā)
  • 真實(shí)對(duì)象實(shí)際上還不存在的(和其他開(kāi)發(fā)小組或者和新的硬件打交道)等等

使用 Mock 對(duì)象測(cè)試的關(guān)鍵步驟

  • 使用一個(gè)接口來(lái)描述這個(gè)對(duì)象
  • 在產(chǎn)品代碼中實(shí)現(xiàn)這個(gè)接口
  • 在測(cè)試代碼中實(shí)現(xiàn)這個(gè)接口
  • 在被測(cè)試代碼中只是通過(guò)接口來(lái)引用對(duì)象,所以它不知道這個(gè)引用的對(duì)象是真實(shí)對(duì)象,還是 Mock 對(duì)象。

Mock 與Stub 的區(qū)別

Mock 不是 Stub,兩者是有區(qū)別的:

  • 前者被稱(chēng)為 mockist TDD,而后者一般稱(chēng)為 classic TDD ;
  • 前者是基于行為的驗(yàn)證(behavior verification),后者是基于狀態(tài)的驗(yàn)證 (state verification);
  • 前者使用的是模擬的對(duì)象,而后者使用的是真實(shí)的對(duì)象。

Java Mock 測(cè)試

目前,在 Java 陣營(yíng)中主要的 Mock 測(cè)試工具有 Mockito,JMock,EasyMock 等。

關(guān)于這些框架的比較,不是本文的重點(diǎn)。本文著重介紹 Mockito 的使用。

Mockito 的特性

Mockito 是美味的 Java 單元測(cè)試 Mock 框架,開(kāi)源。

大多 Java Mock 庫(kù)如 EasyMock 或 JMock 都是 expect-run-verify (期望-運(yùn)行-驗(yàn)證)方式,而 Mockito 則使用更簡(jiǎn)單,更直觀的方法:在執(zhí)行后的互動(dòng)中提問(wèn)。使用 Mockito,你可以驗(yàn)證任何你想要的。而那些使用 expect-run-verify 方式的庫(kù),你常常被迫查看無(wú)關(guān)的交互。

非 expect-run-verify 方式 也意味著,Mockito 無(wú)需準(zhǔn)備昂貴的前期啟動(dòng)。他們的目標(biāo)是透明的,讓開(kāi)發(fā)人員專(zhuān)注于測(cè)試選定的行為。

Mockito 擁有的非常少的 API,所有開(kāi)始使用 Mockito,幾乎沒(méi)有時(shí)間成本。因?yàn)橹挥幸环N創(chuàng)造 mock 的方式。只要記住,在執(zhí)行前 stub,而后在交互中驗(yàn)證。你很快就會(huì)發(fā)現(xiàn)這樣 TDD java 代碼是多么自然。

類(lèi)似 EasyMock 的語(yǔ)法來(lái)的,所以你可以放心地重構(gòu)。Mockito 并不需要“expectation(期望)”的概念。只有 stub 和驗(yàn)證。

Mockito 實(shí)現(xiàn)了 Gerard Meszaros 所謂的 Test Spy.

其他的一些特點(diǎn):

  • 可以 mock 具體類(lèi)而不單止是接口
  • 一點(diǎn)注解語(yǔ)法糖 - @Mock
  • 干凈的驗(yàn)證錯(cuò)誤是 - 點(diǎn)擊堆棧跟蹤,看看在測(cè)試中的失敗驗(yàn)證;點(diǎn)擊異常的原因來(lái)導(dǎo)航到代碼中的實(shí)際互動(dòng)。堆棧跟蹤總是干干凈凈。
  • 允許靈活有序的驗(yàn)證(例如:你任意有序 verify,而不是每一個(gè)單獨(dú)的交互)
  • 支持“詳細(xì)的用戶(hù)號(hào)碼的時(shí)間”以及“至少一​​次”驗(yàn)證
  • 靈活的驗(yàn)證或使用參數(shù)匹配器的 stub (anyObject(),anyString() 或 refEq() 用于基于反射的相等匹配)
  • 允許創(chuàng)建自定義的參數(shù)匹配器或者使用現(xiàn)有的 hamcrest 匹配器

Mockito 入門(mén)

聲明 mockito 依賴(lài)

Gradle 用戶(hù)可以使用:

repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:1.+" }

示例

1.驗(yàn)證行為

//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();

一旦創(chuàng)建 mock 將會(huì)記得所有的交互。你可以選擇驗(yàn)證你感興趣的任何交互

2.stubbing

//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);

  • 默認(rèn)情況下,所有方法都會(huì)返回值,一個(gè) mock 將返回要么 null,一個(gè)原始/基本類(lèi)型的包裝值或適當(dāng)?shù)目占?。例如,?duì)于一個(gè) int/Integer 就是 0,而對(duì)于 boolean/Boolean 就是 false。
  • Stubbing 可以被覆蓋。
  • 一旦 stub,該方法將始終返回一個(gè) stub 的值,無(wú)論它有多少次被調(diào)用。
  • 最后的 stubbing 是很重要的 - 當(dāng)你使用相同的參數(shù) stub 多次同樣的方法。換句話說(shuō):stubbing 的順序是重要的,但它唯一有意義的卻很少,例如當(dāng) stubbing 完全相同的方法調(diào)用,或者有時(shí)當(dāng)參數(shù)匹配器的使用,等等。

3.參數(shù)匹配器

Mockito 驗(yàn)證參數(shù)值使用 Java 方式:通過(guò)使用 equals() 方法。有時(shí),當(dāng)需要額外的靈活性,可以使用參數(shù)匹配器:

//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());

參數(shù)匹配器允許靈活的驗(yàn)證或 stubbing。點(diǎn)擊這里查看更多內(nèi)置的匹配器和自定義的參數(shù)匹配器/ hamcrest匹配器的例子。

自定義參數(shù)的匹配信息,請(qǐng)查看 Javadoc 中 ArgumentMatcher 類(lèi)。

如果你正在使用參數(shù)的匹配,所有的參數(shù)都由匹配器來(lái)提供。

下面的示例演示驗(yàn)證,但同樣適用于 stubbing:

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.

4.調(diào)用額外的調(diào)用數(shù)字/at least x / never

//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("five times");
verify(mockedList, atMost(5)).add("three times");

times(1) 是默認(rèn)的,因此,使用的 times(1) 可以顯示的省略。

5.Stubbing void 方法處理異常

doThrow(new RuntimeException()).when(mockedList).clear();
//following throws RuntimeException:
mockedList.clear();

6.有序的驗(yàn)證

// 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

有序驗(yàn)證是為了靈活 - 你不必一個(gè)接一個(gè)驗(yàn)證所有的交互。

此外,您還可以通過(guò)創(chuàng)建 InOrder 對(duì)象傳遞只與有序驗(yàn)證相關(guān)的 mock 。

7. 確保 mock 上不會(huì)發(fā)生交互

//using mocks - only mockOne is interacted
mockOne.add("one");
//ordinary verification
verify(mockOne).add("one");
//verify that method was never called on a mock
verify(mockOne, never()).add("two");
//verify that other mocks were not interacted
verifyZeroInteractions(mockTwo, mockThree);

8.尋找多余的調(diào)用

//using mocks
mockedList.add("one");
mockedList.add("two");
verify(mockedList).add("one");
//following verification will fail
verifyNoMoreInteractions(mockedList);

注意:不建議 verifyNoMoreInteractions() 在每個(gè)測(cè)試方法中使用。 verifyNoMoreInteractions() 是從交互測(cè)試工具包一個(gè)方便的斷言。只有與它的相關(guān)時(shí)才使用它。濫用它導(dǎo)致難以維護(hù)。

9. 標(biāo)準(zhǔn)創(chuàng)建 mock 方式 - 使用 @Mock 注解

  • 最小化可重用 mock 創(chuàng)建代碼
  • 使測(cè)試類(lèi)更加可讀性
  • 使驗(yàn)證錯(cuò)誤更加易讀,因?yàn)樽侄蚊Q(chēng)用于唯一識(shí)別 mock
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider;
private ArticleManager manager;

在基礎(chǔ)類(lèi)或者測(cè)試 runner 里面,使用如下:

MockitoAnnotations.initMocks(testClass);

可以使用內(nèi)建 runner: MockitoJUnitRunner 或者 rule: MockitoRule

10. Stubbing 連續(xù)調(diào)用(迭代器式的 stubbing)

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"));

下面是一個(gè)精簡(jiǎn)版本:

when(mock.someMethod("some arg"))
.thenReturn("one", "two", "three");

11. 回調(diào) Stubbing

允許使用泛型 Answer 接口。

然而,這是不包括在最初的 Mockito 另一個(gè)有爭(zhēng)議的功能。我們建議您只需用thenReturn() 或 thenThrow() 來(lái) stubbing ,這在測(cè)試/測(cè)試驅(qū)動(dòng)中應(yīng)用簡(jiǎn)潔與簡(jiǎn)單的代碼足夠了。但是,如果你有一個(gè)需要 stub 到泛型 Answer 接口,這里是一個(gè)例子:

when(mock.someMethod(anyString())).thenAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Object mock = invocation.getMock();
return "called with arguments: " + args;
}
});
//the following prints "called with arguments: foo"
System.out.println(mock.someMethod("foo"));

12. doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod() 家族方法

Stubbing void 方法,需要不同的 when(Object) ,因?yàn)榫幾g器不喜歡括號(hào)內(nèi)無(wú)效的方法…

在 用于 Stubbing void 方法中,doThrow(Throwable…) 取代 stubVoid(Object)。主要原因是提高可讀性和與 doAnswer() 保持一致性。

當(dāng)你想用 stub void 方法 使用 doThrow():

doThrow(new RuntimeException()).when(mockedList).clear();
//following throws RuntimeException:
mockedList.clear();

在調(diào)用 when() 的相應(yīng)地方可以使用 oThrow(), doAnswer(), doNothing(), doReturn() 和 doCallRealMethod(),當(dāng):

  • stub void 方法
  • stub 方法在 spy 對(duì)象(見(jiàn)下面)
  • 可以不止一次的 stub 相同的方法,在測(cè)試的中期來(lái)改變 mock 的行為

但你更加傾向于使用這些方法來(lái)代替 when(),在所有的 stubbing 調(diào)用。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • maven?helper?jar包沖突的幾種解決方法

    maven?helper?jar包沖突的幾種解決方法

    maven Helper是排查jar包沖突的一大利器,jar包沖突大部分是由于引用了同一個(gè)jar的不同版本而導(dǎo)致的,本文主要介紹了maven?helper?jar包沖突的幾種解決方法,感興趣的可以了解一下
    2024-03-03
  • 使用jib插件為Java應(yīng)用構(gòu)建鏡像的方法

    使用jib插件為Java應(yīng)用構(gòu)建鏡像的方法

    這篇文章主要介紹了使用jib插件為Java應(yīng)用構(gòu)建鏡像,要是用戶(hù)本地沒(méi)安裝docker,可以使用jib制作出帶有鏡像的tar文件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • Java 數(shù)據(jù)結(jié)構(gòu)之刪除鏈表中重復(fù)的結(jié)點(diǎn)

    Java 數(shù)據(jù)結(jié)構(gòu)之刪除鏈表中重復(fù)的結(jié)點(diǎn)

    在一個(gè)排序的鏈表中,會(huì)存在重復(fù)的結(jié)點(diǎn),如何實(shí)現(xiàn)刪除該鏈表中重復(fù)的結(jié)點(diǎn),重復(fù)的結(jié)點(diǎn)不保留,并返回鏈表頭指針呢?接下來(lái)小編將帶你詳細(xì)介紹
    2021-12-12
  • mybatis如何實(shí)現(xiàn)的數(shù)據(jù)庫(kù)排序

    mybatis如何實(shí)現(xiàn)的數(shù)據(jù)庫(kù)排序

    這篇文章主要介紹了mybatis如何實(shí)現(xiàn)的數(shù)據(jù)庫(kù)排序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java實(shí)現(xiàn)順序表和鏈表結(jié)構(gòu)

    Java實(shí)現(xiàn)順序表和鏈表結(jié)構(gòu)

    大家好,本篇文章主要講的是Java實(shí)現(xiàn)順序表和鏈表結(jié)構(gòu),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • Springboot如何優(yōu)雅的關(guān)閉應(yīng)用

    Springboot如何優(yōu)雅的關(guān)閉應(yīng)用

    這篇文章主要介紹了Springboot如何優(yōu)雅的關(guān)閉應(yīng)用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • MAVEN的安裝配置與IDEA整合超詳細(xì)教程

    MAVEN的安裝配置與IDEA整合超詳細(xì)教程

    這篇文章給大家介紹了MAVEN的安裝,配置與IDEA整合方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,感興趣的朋友跟隨小編一起看看吧
    2021-02-02
  • @SpringBootConfiguration重復(fù)加載報(bào)錯(cuò)問(wèn)題解決

    @SpringBootConfiguration重復(fù)加載報(bào)錯(cuò)問(wèn)題解決

    @SpringBootApplication?注解的?exclude?屬性用于排除特定的自動(dòng)配置類(lèi),而不是用于排除主配置類(lèi)本身,因此,不能通過(guò)?exclude?屬性來(lái)排除主配置類(lèi)的加載,這篇文章主要介紹了@SpringBootConfiguration重復(fù)加載報(bào)錯(cuò),需要的朋友可以參考下
    2024-08-08
  • Spring Bean初始化及銷(xiāo)毀多種實(shí)現(xiàn)方式

    Spring Bean初始化及銷(xiāo)毀多種實(shí)現(xiàn)方式

    這篇文章主要介紹了Spring Bean初始化及銷(xiāo)毀多種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot的攔截器中依賴(lài)注入為null的解決方法

    SpringBoot的攔截器中依賴(lài)注入為null的解決方法

    這篇文章主要介紹了SpringBoot的攔截器中依賴(lài)注入為null的解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06

最新評(píng)論