您可以在Swift加载应用程序之前进行测试设置吗?

时间:2020-05-23 17:40:42

标签: swift xcode macos unit-testing

我是一名Swift / MacOS新手,正在MacOS应用程序上进行一些设置,其中涉及在主ViewController的viewDidLoad()方法中进行钥匙串访问和API调用。

我正在为我的模型进行单元测试,因此我不需要,实际上也不想运行viewDidLoad()中的代码。但是,据我所知,该应用程序已加载,并且这些方法在测试用例setup()方法之前运行,所以我不知道该如何做任何模拟或其他操作。

我正在使用Xcode 11.5和Swift 5。

1 个答案:

答案 0 :(得分:1)

一种方法是在运行单元测试时使用单独的NSApplicationMain,而在“正常”运行时使用单独的@NSApplicationMain

首先从您当前的AppDelegate类中删除import AppKit class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { print("Debug/Production run") // Insert code here to initialize your application } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } } 批注。它最终应该看起来像这样:

AppDelegate.swift

AppDelegateUnitTesting.swift

现在创建一个名为import Foundation import Cocoa class AppDelegateTesting: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { print("Unit Testing Run") // Insert code here to initialize your application } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } } 的新文件,其来源应如下所示:

AppDelegateUnitTesting.swift

main.swift

现在添加一个名为import Foundation import Cocoa let isRunningTests = NSClassFromString("XCTestCase") != nil && ProcessInfo.processInfo.arguments.contains("-XCUnitTests") fileprivate var delegate: NSApplicationDelegate? if !isRunningTests { delegate = AppDelegate() NSApplication.shared.delegate = delegate // See this Answer to initialize the Windows programmatically // https://stackoverflow.com/a/44604229/496351 } else { delegate = AppDelegateTesting() NSApplication.shared.delegate = delegate } NSApplication.shared.run() 的新文件,该文件将确定我们的应用在哪个环境中运行,源应为以下内容:

main.swift

XCTestClass

要确定它是否在单元测试环境中运行,它会检查是否可以加载-XCUnitTest(仅在测试时注入),并检查是否存在Test命令行参数,我们必须在方案"Debug/Production run"动作中自行设置该参数,如下图所示

Test Args

完成所有这些操作后,按播放按钮时,应该会看到消息"Unit Testing Run",并且每次运行单元测试时都应该看到消息const GlobalStyle = createGlobalStyle` body { background: ${props => (props.something ? url(imageone) : url(imagetwo))}; } `

您很可能必须添加代码以编程方式加载初始窗口,而另一个答案说明了如何做到这一点: