成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iOS單元測(cè)試:譯-OCMock常見使用方式

移動(dòng)開發(fā) iOS
當(dāng)我們寫單元測(cè)試的時(shí)候,不可避免的要去盡可能少的實(shí)例化一些具體的組件來保持測(cè)試既短又快。而且保持單元的隔離。在現(xiàn)代的面向?qū)ο笙到y(tǒng)中,測(cè)試的組件很可能會(huì)有幾個(gè)依賴的對(duì)象。我們用mock來替代實(shí)例化具體的依賴class。

該文章使用的API是OCMock老版本的API,新版本也兼容老版本的API,譯者在用到老版本的API處已經(jīng)添加了對(duì)應(yīng)的新版本(OCMock3)的API供讀者參考。

愛好者

這篇文章假設(shè)讀者都能熟悉使用Xcode5的測(cè)試框架XCTest,或者BBD測(cè)試工具Kiwi或其他的iOS測(cè)試框架

 

[[133631]]

什么是mock?差不多就是紙老虎
 

當(dāng)我們寫單元測(cè)試的時(shí)候,不可避免的要去盡可能少的實(shí)例化一些具體的組件來保持測(cè)試既短又快。而且保持單元的隔離。在現(xiàn)代的面向?qū)ο笙到y(tǒng)中,測(cè)試的組件很可能會(huì)有幾個(gè)依賴的對(duì)象。我們用mock來替代實(shí)例化具體的依賴class。mock是在測(cè)試中的一個(gè)偽造的有預(yù)定義行為的具體對(duì)象的替身對(duì)象。被測(cè)試的組件不知道其中的差異!你的組件是在一個(gè)更大的系統(tǒng)中被設(shè)計(jì)的,你可以很有信心的用mock來測(cè)試你的組件。

常見的mock使用案例

stub方法

我們用一個(gè)簡(jiǎn)單的例子來開始解釋OCMock中一般的stub語法。

  1. id jalopy = [OCMock mockForClass[Car class]];  
  2.  [[[jalopy stub] andReturn:@"75kph"] goFaster:[OCMArg any] units:@"kph"];  
  3.  // if returning a scalar value, andReturnValue: can be used 

OCMock3 新版本對(duì)應(yīng)API

  1. id jalopy = OCMStrictClassMock([Car class]);  
  2. OCMStub([jalopy goFaster:[OCMArg any] units:@"kph"]).andReturn(@"75kph");  
  3. // if returning a scalar value, andReturnValue: can be used 

這個(gè)簡(jiǎn)單的例子首先從Car類中mock出一個(gè)jalopy(老爺車),然后,stub掉goFaster:方法讓它返回字符串@”75kph”。stub語法可能看起來有點(diǎn)奇怪,但這是普遍的做法:

  1. ourMockObject stub] whatItShouldReturn ] method: 

OCMock3 新版本對(duì)應(yīng)API

  1. OCMStub([ourMockObject method:]).andReturn() 

一個(gè)非常重要的說明:注意[OCMArg any]的用法。當(dāng)指定一個(gè)帶參數(shù)的方法時(shí),方法被調(diào)用并且參數(shù)為指定參數(shù)的話,mock會(huì)返回andReturn:指定的值。[OCMArg any]方法告訴stub匹配所有的參數(shù)值。舉個(gè)例子:

  1. [car goFaster:84 units:@"mph"]; 

不會(huì)觸發(fā)stub,因?yàn)樽詈笠粋€(gè)參數(shù)不匹配”kph”.

類方法

OCMock會(huì)在mock實(shí)例上沒有找到相同名字的實(shí)例方法的時(shí)候去找同名的類方法。在名字相同的情況下(類方法和實(shí)例方法同名),用classMethod來指定類方法:

  1. [[[[jalopy stub] classMethod] andReturn:@"expired"] checkWarrany]; 

在OCMock3中classMethod和instanceMethod的stub方式一樣,例如:

  1. id classMock = OCMClassMock([SomeClass class]);  
  2. OCMStub([classMock aClassMethod]).andReturn(@"Test string");  
  3. // result is @"Test string"  
  4. NSString *result = [SomeClass aClassMethod]; 

mock類型 – niceMock,partialMock
OCMock提供了幾種不同類型的mock,每個(gè)都有他們特定的使用場(chǎng)景。

用這種方式來創(chuàng)建任意mock:

  1. id mockThing = [OCMock mockForClass[Thing class]]; 

OCMock3 新版本對(duì)應(yīng)API

  1. id mockThing = OCMStrictClassMock([Thing class]); 

這就是我所說的‘vanilla’ mock。‘vanilla’ mock當(dāng)調(diào)用一個(gè)沒有stub的方法的時(shí)候會(huì)拋出一個(gè)異常。這會(huì)得到一個(gè)單調(diào)的mock,且在mock的生命周期中每一個(gè)方法調(diào)用都要被stub掉。(更多信息請(qǐng)看下一節(jié)關(guān)于stub)

如果你不想stub很多方法,用‘nice’ mock。‘nice’ mock非常有禮貌而且不會(huì)在一個(gè)沒有stub掉的方法被調(diào)用的時(shí)候拋出異常。

  1. id niceMockThing = [OCMock niceMockForClass[Thing class]]; 

OCMock3 新版本對(duì)應(yīng)API

  1. id mockThing = OCMClassMock([Thing class]); 

最后一個(gè)mock類型是‘partial’ mock。當(dāng)一個(gè)沒有stub掉的方法被調(diào)用了,這個(gè)方法會(huì)被轉(zhuǎn)發(fā)到真實(shí)的對(duì)象上。這是對(duì)mock技術(shù)上的欺騙,但是非常有用,當(dāng)有一些類不適合讓自己很好的被stub。

  1. Thing *someThing = [Thing alloc] init];  
  2. id aMock = [OCMockObject partialMockForObject:someThing] 

OCMock3 新版本對(duì)應(yīng)API

  1. Thing *someThing = [Thing alloc] init];  
  2. id aMock = OCMPartialMock(someThing); 

驗(yàn)證方法是否被調(diào)用

驗(yàn)證方法是否被調(diào)用非常簡(jiǎn)單。這個(gè)可以用expect來完成拒絕和驗(yàn)證方法:

  1. id niceMockThing = [OCMock niceMockForClass[Thing class]];  
  2.  [[niceMockThing expect] greeting:@"hello"];  
  3.  // verify the method was called as expected  
  4.  [niceMocking verify]; 

OCMock3 新版本對(duì)應(yīng)API

  1. id niceMockThing = OCMClassMock([Thing class]);  
  2. OCMVerify([niceMockThing greeting:@"hello"]); 

當(dāng)被驗(yàn)證的方法沒有被調(diào)用的時(shí)候會(huì)拋出異常。如果你用的是XCTest,那么請(qǐng)用XCTAssertNotThrow來包裝驗(yàn)證調(diào)用。拒絕方法調(diào)用也是同樣的道理,但是會(huì)再方法調(diào)用的時(shí)候拋出異常。就像stub,selector和傳遞過去驗(yàn)證的參數(shù)必須匹配調(diào)用時(shí)候傳遞過去的參數(shù)。用[OCMArg any]可以簡(jiǎn)化我們的工作。

處理block參數(shù)

OCMock也可以處理block回調(diào)參數(shù)。block回調(diào)通常用于網(wǎng)絡(luò)代碼,數(shù)據(jù)庫代碼,或者在任何異步操作中。在這個(gè)例子中,思考下下面的方法:

  1. - (void)downloadWeatherDataForZip:(NSString *)zip  
  2.               callback:(void (^)(NSDictionary *response))callback; 

在這個(gè)例子中,我們有一個(gè)下載天氣壓縮數(shù)據(jù)的方法,并且把下載下來的dictionary代理到一個(gè)block的回調(diào)中。在測(cè)試中,我們通過預(yù)定義的天氣數(shù)據(jù)來測(cè)試回調(diào)處理。這也是明智的測(cè)試失敗場(chǎng)景。你永遠(yuǎn)不會(huì)知道網(wǎng)絡(luò)上會(huì)返回你什么東西!

  1. // 1. stub using OCMock andDo: operator.  
  2. [[[groupModelMock stub] andDo:^(NSInvocation *invoke) {  
  3.         //2. declare a block with same signature  
  4.         void (^weatherStubResponse)(NSDictionary *dict);  
  5.         //3. link argument 3 with with our block callback  
  6.         [invoke getArgument:&weatherStubResponse atIndex:3];  
  7.         //4. invoke block with pre-defined input  
  8.         NSDictionary *testResponse = @{@"high": 43 , @"low": 12};  
  9.         weatherStubResponse(groupMemberMock);  
  10.     }]downloadWeatherDataForZip@"80304" callback:[OCMArg any] ]; 

OCMock3 新版本對(duì)應(yīng)API

  1. // 1. stub using OCMock andDo: operator.  
  2. OCMStub([groupModelMock downloadWeatherDataForZip:@"80304" callback:[OCMArg any]]]).andDo(^(NSInvocation *invocation){  
  3.         //2. declare a block with same signature  
  4.         void (^weatherStubResponse)(NSDictionary *dict);  
  5.         //3. link argument 3 with with our block callback  
  6.         [invoke getArgument:&weatherStubResponse atIndex:3];  
  7.         //4. invoke block with pre-defined input  
  8.         NSDictionary *testResponse = @{@"high": 43 , @"low": 12};  
  9.         weatherStubResponse(groupMemberMock);  
  10.     }); 

這里的大體思想相當(dāng)簡(jiǎn)單,即便如此,他的實(shí)現(xiàn)也需要一些說明:

1.這個(gè)mock對(duì)象使用帶NSInvocation參數(shù)的“andDo”方法。一個(gè)NSInvocation對(duì)象代表一個(gè)‘objectivetified’(實(shí)在不知道這個(gè)什么鬼)表現(xiàn)的方法調(diào)用。通過這個(gè)NSinvocation對(duì)象,使得攔截傳遞給我們的方法的block參數(shù)變得可能。

2.用與我們測(cè)試的方法中相同的方法簽名聲明一個(gè)block參數(shù)。

3.NSInvocation實(shí)例方法"getArgument:atIndex:"將賦值后的塊函數(shù)傳遞都原始函數(shù)中定義的塊函數(shù)中。注意:在Objective-C中,傳遞給任意方法的前兩個(gè)參數(shù)都是“self”和“_cmd”.這是一個(gè)運(yùn)行時(shí)的小功能以及用下標(biāo)來獲取NSInvocation參數(shù)時(shí)我們需要考慮的東西。

4.最后,傳遞這個(gè)回調(diào)的預(yù)定義字典。

最后

希望這篇文章和例子已經(jīng)陳述清楚一些OCMock最通用的用法。OCMock站點(diǎn):http://ocmock.org/features/是一個(gè)最好的學(xué)習(xí)OCMock的地方。mock是單調(diào)的但是對(duì)于一個(gè)現(xiàn)代的OO系統(tǒng)卻是必須的。如果一個(gè)依賴圖很難用mock來測(cè)試,這個(gè)跡象表明你的設(shè)計(jì)需要重新考慮了。

責(zé)任編輯:林師授 來源: github
相關(guān)推薦

2022-04-27 08:17:07

OCMock單元測(cè)試集成

2020-05-07 17:30:49

開發(fā)iOS技術(shù)

2012-05-21 09:41:54

XcodeiOS單元測(cè)試

2017-01-14 23:26:17

單元測(cè)試JUnit測(cè)試

2017-01-16 12:12:29

單元測(cè)試JUnit

2017-01-14 23:42:49

單元測(cè)試框架軟件測(cè)試

2017-03-23 16:02:10

Mock技術(shù)單元測(cè)試

2023-07-26 08:58:45

Golang單元測(cè)試

2012-05-17 09:09:05

Titanium單元測(cè)試

2013-06-04 09:49:04

Spring單元測(cè)試軟件測(cè)試

2011-07-27 13:39:28

iOS GH-Unit 單元測(cè)試

2017-03-28 12:25:36

2021-03-28 23:03:50

Python程序員編碼

2024-10-16 16:09:32

2010-03-04 15:40:14

Python單元測(cè)試

2009-09-01 16:45:00

C#單元測(cè)試工具

2020-08-18 08:10:02

單元測(cè)試Java

2019-01-29 09:00:44

PyHamcrest單元測(cè)試框架

2023-08-02 13:59:00

GoogleTestCTest單元測(cè)試

2021-05-05 11:38:40

TestNGPowerMock單元測(cè)試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 中文字幕一区二区三区精彩视频 | 久久久久成人精品免费播放动漫 | 日韩成年人视频在线 | 日韩在线视频一区二区三区 | 欧美三级视频在线观看 | 欧美精品在线看 | 在线国产精品一区 | 国产成人免费网站 | 一级片av | 久久9热| 国产精品一区二区欧美黑人喷潮水 | 久久国产精品视频 | 亚洲国产成人在线视频 | 日本精品一区二区在线观看 | 欧美8一10sex性hd | sese视频在线观看 | 欧美福利| 免费人成在线观看网站 | 免费看a | 久久午夜精品 | 成人动慢 | 国产精品一级在线观看 | 亚洲成人免费在线观看 | 国产精品国产三级国产aⅴ中文 | av在线影院 | 理论片免费在线观看 | 婷婷精品| 性欧美xxxx | 成人a网 | 一区二区av | 81精品国产乱码久久久久久 | av大片在线| 久草久 | 粉嫩一区二区三区国产精品 | 亚洲欧美精品国产一级在线 | 影音先锋欧美资源 | 黑人巨大精品欧美一区二区免费 | 在线观看免费av网 | 91亚洲精| 成人免费毛片在线观看 | 色姑娘av|