我想测试一段使用网络的代码( NSURLConnection 类,具体而言)。代码(让我们称之为 NetworkManager )看起来有点像这样:

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

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

在单元测试中,我想摆脱网络,即。用mock替换 NSURLConnection 对象。我该怎么做?

我尝试创建 NetworkManager 的部分模拟,它将用存根替换 buildConnection 方法。问题是 OCMock 所做的部分嘲笑只是来自外界的短信–从 startNetworkSync 发送 buildConnection 会调用原始方法,而不是存根。

我还尝试通过类别对 NetworkManager 类进行猴子修补。这很有效,我可以轻松地通过其他代码覆盖 buildConnection 方法,并用存根替换真正的 NSURLConnection 。问题是,我发现没有简单的方法可以在测试中获得存根连接–连接是 NetworkManager 的私有部分。

然后我可以继承 NetworkManager ,覆盖 buildConnection 方法,并为创建的连接添加一个实例变量和一个访问器。不过,这似乎是很多代码。

你会如何解决这个问题?我正在寻找一种解决方案,使 NetworkManager 类设计保持干净,并且在测试中不需要太多魔法或代码。

有帮助吗?

解决方案

这是依赖注入旨在解决的问题;如果您使用 startNetworkSyncWithConnection:(NSURLConnection *),您可以使用模拟连接轻松测试该方法。如果您不想更改客户端的API,您甚至可以将 startNetworkSync 作为一个包装器,除了使用 [self buildConnection] 调用该新方法之外什么都不做参数。

其他提示

我修改了OCMock以支持真正的部分模拟,请参阅GitHub上的 repo

我最近使用的另一个解决方案是完全抽象网络接口。如果类需要来自网络的某些数据,它可能会与某些服务器服务进行交互,这些服务可以明确地建模为协议:

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

然后你将拥有一个真正的HTTP实现和一个测试。这意味着更多的工作,但也更好的可测试性。由于测试网络层可以满足您的需求,因此测试不那么脆弱且更加方便。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top