main.m
文件(请参见:https://dev59.com/uGUo5IYBdhLWcg3w3ycF#15725328)。由于似乎 Swift 应用程序是使用
@UIApplicationMain
在 AppDelegate 中初始化的,所以是否可能为测试目标初始化一个单独的 AppDelegate?main.m
文件(请参见:https://dev59.com/uGUo5IYBdhLWcg3w3ycF#15725328)。@UIApplicationMain
在 AppDelegate 中初始化的,所以是否可能为测试目标初始化一个单独的 AppDelegate?强烈不建议在正常代码中添加条件来检查它是否正在被测试。相反,在测试中应该模拟您的AppDelegate
来执行任何您想要的操作。
然后,你可以在每个XCTestCase
的父类的setUp
中替换UIApplication的委托。
class MockAppDelegate:NSObject, UIApplicationDelegate {
}
class BaseTest: XCTestCase {
override func setUp() {
super.setUp()
UIApplication.shared.delegate = MockAppDelegate()
}
}
class Test1: BaseTest {
override func setUp() {
super.setUp()
// normal testing
}
}
如果您仍想在测试中停止代码执行,这是我的方法,可以很好地运行:NSUserDefaults
中访问。#define IS_TESTS [[NSUserDefaults standardUserDefaults] boolForKey:@"TESTING"]
If you are using Storyboards, create your view stack programmatically on your AppDelegate.
Remove Main.storyboard from your project configuration
Delete @UIApplicationMain from the beginning of your AppDelegate and add this code.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateInitialViewController()
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = vc
window.makeKeyAndVisible()
self.window = window
return true
}
Create a new file at the root your target and call it main.swift.
Add this code if you don't need to do any setup for your tests
import UIKit
let kIsRunningTests = NSClassFromString("XCTestCase") != nil
let kAppDelegateClass = kIsRunningTests ? nil : NSStringFromClass(AppDelegate.self)
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, kAppDelegateClass)
If you need to make some configuration before you run the tests, create a new class FakeAppDelegate as a subclass from NSObject and add your setup code there.
Put this code in main.swift
import UIKit
let kIsRunningTests = NSClassFromString("XCTestCase") != nil
let kAppDelegateClass = kIsRunningTests ? NSStringFromClass(FakeAppDelegate.self) : NSStringFromClass(AppDelegate.self)
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, kAppDelegateClass)
复制您现有应用程序的目标,并将其重命名为适当的名称。在您的情况下,可能是“TestingHarness”或类似的名称。请注意,您还需要更改捆绑标识符并重命名相应的Info.plist文件。重命名Info.plist文件意味着您需要在新目标的Build Settings选项卡中更改Info.plist文件名设置以匹配新名称。
创建另一个*AppDelegate.swift
文件。在您的情况下,我会称之为TestAppDelegate.swift
。
将现有的AppDelegate.swift
文件内容复制到TestAppDelegate.swift
中,并根据需要进行编辑。确保保留@UIApplicationMain
注释并实现所需的UIApplicationDelegate
回调。
更改每个*AppDelegate.swift
文件的目标成员资格,以使AppDelegate.swift
不包含在新的“TestHarness”目标中,而TestAppDelegate.swift
不包含在主应用程序的目标中。(您可以通过在文件浏览器中选择它并打开默认情况下可以访问的右侧边栏中的文件检查器,或通过在菜单下选择它来编辑文件的目标成员资格 -> 实用程序。)
现在,您有两个具有单独的应用程序委托的单独目标,可以独立构建和运行。最后一步是将您的新“TestHarness”目标选择为测试目标的主机应用程序。(单击文件浏览器中的顶级项目条目,然后单击子列表中的所需测试目标。在常规选项卡上,您将看到Host Application作为唯一可用的下拉菜单。)
注意:这些说明适用于Xcode 7.2。
AppDelegate
(处理用户和会话状态以及数据存储)中执行。不幸的是,创建一个MockAppDelegate
并不能实现这一点。 - WhoadidFinishLaunchingWithOptions
。 - Marc-Alexandre BérubésetUp()
在正常的应用程序委托运行didFinishLaunchingWithOptions
之后执行。我的测试委托从未被使用。 - UserMockAppDelegate()
变成一个成员、全局变量或以其他方式创建一个强引用。 - MattD