使用 KIF 进行功能测试:加载视图控制器后调用 beforeEach?

Feature tests with KIF: beforeEach is called after my view controller is loaded?

我有一个简单的(我猜)问题。

我想使用 Specta 和 KIF 在我的应用程序中进行功能测试。问题是我在我的视图控制器的 viewDidLoad 方法中设置依赖项,而在我的规范的 beforeEach 方法中我注入假对象只是为了不访问网络。

结果是错误的,因为 viewDidLoad 在规范中的 beforeEach 方法之前被调用。

是否可以在 AppDelegate 加载根视图控制器之前设置依赖项以便一切设置正确?

依赖于目标的测试(如 KIF 和某些单元测试)在应用程序启动后启动,所以不,如果没有一些可怕的 hackery,你不能让 beforeEach 在你的 AppDelegate 之前。

我不知道你是如何进行依赖注入的,所以我们是这样做的it/some一般策略。

KIF 测试最好不要在代码级别进行模拟

这是因为 KIF 是 UIAutomation 的替代品,主要用于 UI 级别的 feature/functional 测试。您真的不想对您的应用程序代码进行如此大的更改。模拟最好使用诸如用于网络的 OHHTTPStubs 或用于对象的 OCMock 之类的框架来实现,这些框架在仅限于单元测试时效果最好。

如何在 "real" 应用程序中模拟网络请求

这里最好的方法是使用 OHHTTPStubs 或 AMY 服务器(由制作 KIF 的同一个人制作)或 Nocilla 之类的东西来 return 存根响应。这样你就可以让你的应用代码 运行 完全。例如,OHHTTPStubs 使用 NSURLProtocol 来拦截您的请求,因此从应用程序的角度来看,它几乎与外出网络一样好。

我真的很想模拟那些对象

如果你真的真的真的很想用不同的对象模拟依赖注入对象,那么有几个或多或少的 hacky 选项。

1) 使用允许修补依赖项的真正的 DI 框架(或构建您自己的框架)。我用过 Typhoon,它是合理的。这里的标准思想是利用控制反转来发挥你的优势。由于您是从应用程序上下文而不是直接获取所有对象,因此调整应用程序上下文抽象层要容易得多。台风甚至有一个关于这个主题的维基页面: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;
}

不幸的是,最终这不是一个简单的"where do I put this method"问题。