我有简单的(我猜)问题。
我想用 Specta 和 KIF 在我的应用程序中进行功能测试。问题是我在 View Controller 的 viewDidLoad 方法中设置依赖关系,而在我的规范的 beforeEach 方法中,我正在注入假对象只是为了不访问网络。
结果是错误的,因为 viewDidLoad 在规范中的 beforeEach 方法之前被调用。
是否有可能在 AppDelegate 加载根视图控制器之前设置依赖项,以便正确设置所有内容?
依赖于目标的测试(如 KIF 和某些单元测试)在应用程序启动后启动,所以不,如果没有一些可怕的骇客,你不能让 beforeEach 在你的 AppDelegate 之前运行。
我不知道您是如何进行依赖注入的,所以这是我们的做法/一些通用策略。
理想情况下,KIF 测试不应在代码级别模拟
这是因为 KIF 是 UIAutomation 的一种替代方案,主要用于 UI 级别的特性/功能测试。您并不想过多地更改您的应用程序代码。Mocks 最好使用 OHHTTPStubs 等框架来实现网络或 OCMock 用于对象,并且在仅限于单元测试时效果最好。
如何在“真实”应用中模拟网络请求
这里最好的方法是使用 OHHTTPStubs 或 AMY 服务器(由制作 KIF 的同一个人制作)或 Nocilla 之类的东西来返回存根响应。这样您就可以让您的应用程序代码完全运行。例如,OHHTTPStubs 使用 NSURLProtocol 来拦截您的请求,因此从应用程序的角度来看,它几乎与访问网络一样好。
我真的很想模拟出那些对象
如果你真的真的很想用不同的对象来模拟依赖注入的对象,那么有几个越来越少的 hacky 选项。
1) 使用允许修补依赖项的真正 DI 框架(或构建您自己的)。我用过Typhoon,它是合理的。这里的标准想法是利用控制反转来发挥您的优势。由于您从应用程序上下文而不是直接获取所有对象,因此调整应用程序上下文抽象层要容易得多。Typhoon 甚至有一个关于这个主题的 wiki 页面:https ://github.com/appsquickly/Typhoon/wiki/Integration-Testing
2)跟踪您要注入的对象的来源,并希望在源头上模拟并更改它。这不是最优雅的,无论如何您都在破解 DI 框架,但也许您没有足够的时间或复杂性来让切换到 DI 框架值得。
3)一路破解到顶层。有一个测试 AppDelegate,它从您的普通 AppDelegate 子类化,并在 KIF 测试期间使用它(当然还有它存根或模拟出您想要的对象)。这并不灵活,但同样,也许您只需要一个测试用例或其他东西:
int main(int argc, char *argv[])
{
int returnValue;
@autoreleasepool {
BOOL inIntegrationTests = NSClassFromString(@"KIFTestCase") != nil;
if (inIntegrationTests) {
returnValue = UIApplicationMain(argc, argv, nil, @"AppDelegateForTest");
}
else {
returnValue = UIApplicationMain(argc, argv, nil, @"AppDelegate");
}
}
return returnValue;
}
不幸的是,最终这不是一个简单的“我该把这个方法放在哪里”的问题。