2009-05-03 190 views
3

我想測試一段使用網絡的代碼(NSURLConnection類,具體而言)。代碼(姑且稱之爲NetworkManager)看起來有點像這樣:使用NSURLConnection進行單元測試

- (id) buildConnection 
{ 
    // some more code and then: 
    return [NSURLConnection …]; 
} 

- (void) startNetworkSync 
{ 
    id connection = [self buildConnection]; 
    //… 
} 

在單元測試中,我想擺脫網絡,即。用模擬替換NSURLConnection對象。我該怎麼做呢?

我試過創建了NetworkManager的部分模擬,它將用存根代替buildConnection方法。問題是部分嘲諷如OCMock所做的僅存根外部世界的消息 - 從startNetworkSync發送buildConnection將調用原始方法,而不是存根。

我也嘗試通過類別猴子修補NetworkManager類。這可以工作,我可以輕鬆地用其他代碼覆蓋buildConnection方法,並用存根替換實際的NSURLConnection。問題是,我發現沒有簡單的方法可以在測試中獲得樁連接 - 連接是NetworkManager的私有部分。

然後,我可以繼承NetworkManager,覆蓋buildConnection方法,併爲創建的連接添加一個實例變量和一個訪問器。不過,這看起來好像很多代碼。

你會如何解決這個問題?我正在尋找一種解決方案,以保持NetworkManager類設計的清潔,並且在測試中不需要太多魔法或代碼。

回答

3

這是一種依賴注入被設計來解決的事情;如果使用startNetworkSyncWithConnection:(NSURLConnection*),則可以使用模擬連接輕鬆測試該方法。如果您不想爲您的客戶更改API,您甚至可以將startNetworkSync作爲一個包裝器,它只會以[self buildConnection]作爲參數來調用該新方法。

+0

好吧,我已經或多或少的這樣做了。客戶對網絡一無所知,他們只發送和接收數據,但我已經添加了向進程注入「外部」連接的方法,這有助於測試。謝謝。 – zoul 2009-05-05 07:09:41

+0

@zoul,請粘貼您的解決方案的代碼。謝謝! – ma11hew28 2011-03-16 17:56:43

2

我修改了OCMock以支持真正的部分模擬,請參閱repo on GitHub

0

我最近使用的另一個解決方案是完全抽象網絡接口。如果該類從網絡上需要一些數據,它可能與可以顯式地建模爲一個協議的一些服務器服務交互:

@protocol SomeNetworkService 
- (NSArray*) allAvailableFoos; 
- (void) insertNewFoo: (Foo*) foo; 
@end 

然後你就會有一個真正的HTTP實現和測試一個。這意味着更多的工作,但也更好的可測試性。由於測試網絡層可以做​​任何您需要的測試,因此測試更簡單,更方便。