SpringBoot 單元測試實(shí)戰(zhàn)(Mockito,MockBean)_第1頁
SpringBoot 單元測試實(shí)戰(zhàn)(Mockito,MockBean)_第2頁
SpringBoot 單元測試實(shí)戰(zhàn)(Mockito,MockBean)_第3頁
SpringBoot 單元測試實(shí)戰(zhàn)(Mockito,MockBean)_第4頁
SpringBoot 單元測試實(shí)戰(zhàn)(Mockito,MockBean)_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第SpringBoot單元測試實(shí)戰(zhàn)(Mockito,MockBean)Iteratoriterator=mock(Iterator.class);

//預(yù)設(shè)當(dāng)iterator調(diào)用next()時(shí)第一次返回hello,第n次都返回world

Mockito.when(iterator.next()).thenReturn("hello").thenReturn("world");

//使用mock的對象

Stringresult=iterator.next()+""+iterator.next()+""+iterator.next();

//驗(yàn)證結(jié)果

Assert.assertEquals("helloworldworld",result);

模擬拋出異常

@Test(expected=IOException.class)//期望報(bào)IO異常

publicvoidwhen_thenThrow()throwsIOException{

OutputStreammock=Mockito.mock(OutputStream.class);

//預(yù)設(shè)當(dāng)流關(guān)閉時(shí)拋出異常

Mockito.doThrow(newIOException()).when(mock).close();

mock.close();

}

使用默認(rèn)Answer模擬對象

RETURNS_DEEP_STUBS是創(chuàng)建mock對象時(shí)的備選參數(shù)之一

以下方法deepstubsTest和deepstubsTest2是等價(jià)的

@Test

publicvoiddeepstubsTest(){

Aa=Mockito.mock(A.class,Mockito.RETURNS_DEEP_STUBS);

Mockito.when(a.getB().getName()).thenReturn("Beijing");

Assert.assertEquals("Beijing",a.getB().getName());

@Test

publicvoiddeepstubsTest2(){

Aa=Mockito.mock(A.class);

Bb=Mockito.mock(B.class);

Mockito.when(a.getB()).thenReturn(b);

Mockito.when(b.getName()).thenReturn("Beijing");

Assert.assertEquals("Beijing",a.getB().getName());

classA{

privateBb;

publicBgetB(){

returnb;

publicvoidsetB(Bb){

this.b=b;

classB{

privateStringname;

publicStringgetName(){

returnname;

publicvoidsetName(Stringname){

=name;

publicStringgetSex(Integersex){

if(sex==1){

return"man";

}else{

return"woman";

參數(shù)匹配

@Test

publicvoidwith_arguments(){

Bb=Mockito.mock(B.class);

//預(yù)設(shè)根據(jù)不同的參數(shù)返回不同的結(jié)果

Mockito.when(b.getSex(1)).thenReturn("男");

Mockito.when(b.getSex(2)).thenReturn("女");

Assert.assertEquals("男",b.getSex(1));

Assert.assertEquals("女",b.getSex(2));

//對于沒有預(yù)設(shè)的情況會(huì)返回默認(rèn)值

Assert.assertEquals(null,b.getSex(0));

classB{

privateStringname;

publicStringgetName(){

returnname;

publicvoidsetName(Stringname){

=name;

publicStringgetSex(Integersex){

if(sex==1){

return"man";

}else{

return"woman";

}

匹配任意參數(shù)

Mockito.anyInt()任何int值;

Mockito.anyLong()任何long值;

Mockito.anyString()任何String值;

Mockito.any(XXX.class)任何XXX類型的值等等。

@Test

publicvoidwith_unspecified_arguments(){

Listlist=Mockito.mock(List.class);

//匹配任意參數(shù)

Mockito.when(list.get(Mockito.anyInt())).thenReturn(1);

Mockito.when(list.contains(Mockito.argThat(newIsValid()))).thenReturn(true);

Assert.assertEquals(1,list.get(1));

Assert.assertEquals(1,list.get(999));

Assert.assertTrue(list.contains(1));

Assert.assertTrue(!list.contains(3));

classIsValidextendsArgumentMatcherList{

@Override

publicbooleanmatches(Objectobj){

returnobj.equals(1)||obj.equals(2);

}

注意:使用了參數(shù)匹配,那么所有的參數(shù)都必須通過matchers來匹配

Mockito繼承Matchers,anyInt()等均為Matchers方法

當(dāng)傳入兩個(gè)參數(shù),其中一個(gè)參數(shù)采用任意參數(shù)時(shí),指定參數(shù)需要matchers來對比

Comparatorcomparator=mock(Comparator.class);

pare("nihao","hello");

//如果你使用了參數(shù)匹配,那么所有的參數(shù)都必須通過matchers來匹配

Mockito.verify(comparator).compare(Mockito.anyString(),Mockito.eq("hello"));

//下面的為無效的參數(shù)匹配使用

//verify(comparator).compare(anyString(),"hello");

自定義參數(shù)匹配

@Test

publicvoidargumentMatchersTest(){

//創(chuàng)建mock對象

ListStringmock=mock(List.class);

//argThat(MatchesTmatcher)方法用來應(yīng)用自定義的規(guī)則,可以傳入任何實(shí)現(xiàn)Matcher接口的實(shí)現(xiàn)類。

Mockito.when(mock.addAll(Mockito.argThat(newIsListofTwoElements()))).thenReturn(true);

Assert.assertTrue(mock.addAll(Arrays.asList("one","two","three")));

classIsListofTwoElementsextendsArgumentMatcherList

publicbooleanmatches(Objectlist)

return((List)list).size()==3;

預(yù)期回調(diào)接口生成期望值

@Test

publicvoidanswerTest(){

ListmockList=Mockito.mock(List.class);

//使用方法預(yù)期回調(diào)接口生成期望值(Answer結(jié)構(gòu))

Mockito.when(mockList.get(Mockito.anyInt())).thenAnswer(newCustomAnswer());

Assert.assertEquals("helloworld:0",mockList.get(0));

Assert.assertEquals("helloworld:999",mockList.get(999));

privateclassCustomAnswerimplementsAnswerString{

@Override

publicStringanswer(InvocationOnMockinvocation)throwsThrowable{

Object[]args=invocation.getArguments();

return"helloworld:"+args[0];

}

等價(jià)于:(也可使用匿名內(nèi)部類實(shí)現(xiàn))

@Test

publicvoidanswer_with_callback(){

//使用Answer來生成我們我們期望的返回

Mockito.when(mockList.get(Mockito.anyInt())).thenAnswer(newAnswerObject(){

@Override

publicObjectanswer(InvocationOnMockinvocation)throwsThrowable{

Object[]args=invocation.getArguments();

return"helloworld:"+args[0];

Assert.assertEquals("helloworld:0",mockList.get(0));

Assert.assertEquals("helloworld:999",mockList.get(999));

}

預(yù)期回調(diào)接口生成期望值(直接執(zhí)行)

@Test

publicvoidtestAnswer1(){

ListStringmock=Mockito.mock(List.class);

Mockito.doAnswer(newCustomAnswer()).when(mock).get(Mockito.anyInt());

Assert.assertEquals("大于三",mock.get(4));

Assert.assertEquals("小于三",mock.get(2));

publicclassCustomAnswerimplementsAnswerString{

publicStringanswer(InvocationOnMockinvocation)throwsThrowable{

Object[]args=invocation.getArguments();

Integernum=(Integer)args[0];

if(num3){

return"大于三";

}else{

return"小于三";

}

修改對未預(yù)設(shè)的調(diào)用返回默認(rèn)期望(指定返回值)

//mock對象使用Answer來對未預(yù)設(shè)的調(diào)用返回默認(rèn)期望值

Listmock=Mockito.mock(List.class,newAnswer(){

@Override

publicObjectanswer(InvocationOnMockinvocation)throwsThrowable{

return999;

//下面的get(1)沒有預(yù)設(shè),通常情況下會(huì)返回NULL,但是使用了Answer改變了默認(rèn)期望值

Assert.assertEquals(999,mock.get(1));

//下面的size()沒有預(yù)設(shè),通常情況下會(huì)返回0,但是使用了Answer改變了默認(rèn)期望值

Assert.assertEquals(999,mock.size());

用spy監(jiān)控真實(shí)對象,設(shè)置真實(shí)對象行為

@Test(expected=IndexOutOfBoundsException.class)

publicvoidspy_on_real_objects(){

Listlist=newLinkedList();

Listspy=Mockito.spy(list);

//下面預(yù)設(shè)的spy.get(0)會(huì)報(bào)錯(cuò),因?yàn)闀?huì)調(diào)用真實(shí)對象的get(0),所以會(huì)拋出越界異常

//Mockito.when(spy.get(0)).thenReturn(3);

//使用doReturn-when可以避免when-thenReturn調(diào)用真實(shí)對象api

Mockito.doReturn(999).when(spy).get(999);

//預(yù)設(shè)size()期望值

Mockito.when(spy.size()).thenReturn(100);

//調(diào)用真實(shí)對象的api

spy.add(1);

spy.add(2);

Assert.assertEquals(100,spy.size());

Assert.assertEquals(1,spy.get(0));

Assert.assertEquals(2,spy.get(1));

Assert.assertEquals(999,spy.get(999));

不做任何返回

@Test

publicvoidTest(){

Aa=Mockito.mock(A.class);

//void方法才能調(diào)用doNothing()

Mockito.doNothing().when(a).setName(Mockito.anyString());

a.setName("bb");

Assert.assertEquals("bb",a.getName());

classA{

privateStringname;

privatevoidsetName(Stringname){

=name;

privateStringgetName(){

returnname;

}

調(diào)用真實(shí)的方法

@Test

publicvoidTest(){

Aa=Mockito.mock(A.class);

//void方法才能調(diào)用doNothing()

Mockito.when(a.getName()).thenReturn("bb");

Assert.assertEquals("bb",a.getName());

//等價(jià)于Mockito.when(a.getName()).thenCallRealMethod();

Mockito.doCallRealMethod().when(a).getName();

Assert.assertEquals("zhangsan",a.getName());

classA{

publicStringgetName(){

return"zhangsan";

}

重置mock

@Test

publicvoidreset_mock(){

Listlist=mock(List.class);

Mockito.when(list.size()).thenReturn(10);

list.add(1);

Assert.assertEquals(10,list.size());

//重置mock,清除所有的互動(dòng)和預(yù)設(shè)

Mockito.reset(list);

Assert.assertEquals(0,list.size());

}

@Mock注解

publicclassMockitoTest{

@Mock

privateListmockList;

//必須在基類中添加初始化mock的代碼,否則報(bào)錯(cuò)mock的對象為NULL

publicMockitoTest(){

MockitoAnnotations.initMocks(this);

@Test

publicvoidAnnoTest(){

mockList.add(1);

Mockito.verify(mockList).add(1);

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論