2016-03-11 168 views
1

我正在嘗試OCMock測試是否在viewDidLoad上調用了fetchContactsOnLoad方法。下面的VC代碼。OCMock驗證失敗

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSLog(@"%s", __FUNCTION__); 
    [self fetchContactsOnLoad]; 
} 

-(void)fetchContactsOnLoad { 
    NSLog(@"%s", __FUNCTION__); 
    [self.output doSomething:[ContactListRequest new]]; 
} 

並在下面的測試。

- (void)testFetchContactsOnLoadInvoked { 
    id vcMock = OCMClassMock([ContactListViewController class]); 
    [vcMock view]; 
    OCMVerify([vcMock fetchContactsOnLoad]); 

}

當我運行測試的方法被調用,因爲我能看到的NSLog的打印輸出,但未能通過測試。 我在測試中錯過了什麼?謝謝

回答

0

首先,讓我試着勸阻你試圖測試fetchContactsOnLoad是否被調用。最好是測試的結果發生呼叫fetchContactsOnLoad發生。

這就是說,讓我們繼續。你怎麼能測試fetchContactsOnLoad被調用?這被稱爲「部分模擬」,因爲您只嘲笑對象的零件,但想保留其他所有內容。 (同樣,這通常是一個糟糕的主意,但它可以用於遺留代碼)

我會這樣做的方式是使用傳統測試技術的子類和覆蓋方法。在我的測試代碼,我想創建一個特殊的子類:

@interface TestableContactListViewController : ContactListViewController 
@property (nonatomic, assign) NSUInteger fetchContactsOnLoadCount; 
@end 

@implementation TestableContactListViewController 

- (void)fetchContactsOnLoad { 
    self.fetchContactsOnLoadCount += 1; 
} 

@end 

有了這個地方,測試應該是這樣的:

- (void)testLoadingView_ShouldInvokeFetchContactsOnLoad { 
    TestableContactListViewController *sut = [[TestableContactListViewController alloc] init]; 

    [sut view]; 

    XCTAssertEquals(sut.fetchContactsOnLoadCount, 1); 
} 

注:這不涉及任何嘲弄框架。我手工創建了一個部分模擬。在處理模擬(或部分模擬)時,我建議手動啓動。一旦變得單調乏味,那麼一個嘲諷的框架會讓你更快。但是你會用你所獲得的知識寫出更好的測試。

+0

部分模擬完成了這項工作。我很好奇部分模擬所涉及的風險,並會欣賞一些例子。 在等待某人回覆我的帖子時,我創建並使用了自己的模擬對象,但它需要額外的代碼和重複。除非我找到能自動爲我創建mock的工作,否則我可以做額外的工作。另一個與創建我自己的模擬問題,大部分時間Xcode的覆蓋面沒有采用一種方法(可能要發佈另一個問題,但谷歌的結果似乎很少)。謝謝! – naz

+0

本身沒有技術風險,但不得不使用部分嘲諷通常是一種設計氣味;即一個班級做得太多。通常,最好將不需要被嘲笑的行爲與需要被嘲笑的行爲分開,然後將這兩個部分放入不同的類中。在這種情況下,你可以使用普通模擬器。 OCMock增加了部分模擬功能,主要用於處理基本框架中某些Apple類的類設計。 –