XCTestCase:UIApplication.shared.keyWindow返回nil

时间:2017-01-25 19:31:19

标签: ios swift swift3 xctest

当我打电话

UIApplication.shared.keyWindow

尝试在我的测试类中设置根视图控制器,键窗口返回nil。为什么会这样?

以下是我设置故事板的方法:

let testBoard = UIStoryboard(name: "TestStoryboard", bundle: Bundle(for: type(of: self)))
let vc = testBoard.instantiateViewController(withIdentifier: "TestController")

UIApplication.shared.keyWindow?.rootViewController = vc

_ = vc.view
vc.viewDidLoad()

2 个答案:

答案 0 :(得分:5)

创建一个窗口并分配视图控制器。

let testBoard = UIStoryboard(name: "TestStoryboard", bundle: Bundle(for: type(of: self)))
let vc = testBoard.instantiateViewController(withIdentifier: "TestController")

let window = UIWindow()
window.rootViewController = vc
window.makeKeyAndVisible()

vc.view.layoutIfNeeded()

// Add test here

我注意到你之后还在呼叫vc.viewviewDidLoad。我建议您只是访问视图以加载它而不是隐含地调用viewDidLoad - 我个人使用vc.view.layoutIfNeeded()

根据您实际需要测试的内容,对我来说,很少需要将视图控制器分配给窗口本身。您通常只需创建视图控制器的实例即可,如果您正在测试任何UI代码,也可以确保填充视图。

我需要将视图控制器分配给窗口的唯一一次是在测试导航这样的东西时,我想声明另一个视图控制器由于某些操作而以模态方式呈现。

答案 1 :(得分:0)

在需要访问真实UIWindow但没有自己的测试应用程序的库中测试UI时,我遇到类似的问题。

我的解决方法是添加一个虚拟的iOS单视图目标,然后将其分配为单元测试主机应用程序。

这当然为您的测试代码提供了UIApplication单例,并带有委托和可玩的窗口。

import XCTest
import UIKit

class ExampleTestCase: XCTestCase {
    var rootViewController: UIViewController!

    override func setUp() {
        guard let mainWindow = UIApplication.shared.delegate?.window,
            let window = mainWindow else {
                fatalError("Unable to find window")
        }
        rootViewController = UIViewController()
        window.rootViewController = rootViewController

        setupView()

        window.makeKeyAndVisible()
        RunLoop.current.run(until: Date())
    }
    func setupView() {
        rootViewController.view.backgroundColor = .red
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        label.text = "Hello!"
        label.textColor = .white
        label.font = UIFont.systemFont(ofSize: 25)
        //Do something with window
        rootViewController.view.addSubview(label)
        label.translatesAutoresizingMaskIntoConstraints = false
        label.centerXAnchor.constraint(equalTo: label.superview!.centerXAnchor).isActive = true
        label.centerYAnchor.constraint(equalTo: label.superview!.centerYAnchor).isActive = true
    }

    func testExample() {
        print("Im a useless test!")
    }
}

Setup host app

enter image description here