XCTestCase: UIApplication.shared.keyWindow returns 无
XCTestCase: UIApplication.shared.keyWindow returns nil
当我打电话给
UIApplication.shared.keyWindow
尝试在我的测试中设置根视图控制器 class,键 window returns 无。为什么会这样?
以下是我设置故事板的方式:
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()
创建一个 window 并分配视图控制器。
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.view
和 viewDidLoad
。我建议只访问视图以加载它而不是隐式调用 viewDidLoad
- 我个人使用 vc.view.layoutIfNeeded()
根据您实际需要测试的内容,对我来说很少需要将视图控制器分配给 window 本身。通常,您只需创建一个视图控制器的实例即可,如果您正在测试任何 UI 代码,还要确保视图已填充。
我唯一需要将视图控制器分配给 window 的情况之一是在测试导航之类的东西时,我想断言另一个视图控制器由于某些操作而以模态方式呈现.
我在需要访问真实 UIWindow 但没有自己的测试应用程序的库中测试 UI 时遇到了类似的问题。
我的解决方法是添加一个虚拟 iOS 单一视图目标,然后将其指定为单元测试主机应用程序。
这当然会为您的测试代码提供一个 UI带有委托和 window 的应用程序单例。
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!")
}
}
当我打电话给
UIApplication.shared.keyWindow
尝试在我的测试中设置根视图控制器 class,键 window returns 无。为什么会这样?
以下是我设置故事板的方式:
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()
创建一个 window 并分配视图控制器。
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.view
和 viewDidLoad
。我建议只访问视图以加载它而不是隐式调用 viewDidLoad
- 我个人使用 vc.view.layoutIfNeeded()
根据您实际需要测试的内容,对我来说很少需要将视图控制器分配给 window 本身。通常,您只需创建一个视图控制器的实例即可,如果您正在测试任何 UI 代码,还要确保视图已填充。
我唯一需要将视图控制器分配给 window 的情况之一是在测试导航之类的东西时,我想断言另一个视图控制器由于某些操作而以模态方式呈现.
我在需要访问真实 UIWindow 但没有自己的测试应用程序的库中测试 UI 时遇到了类似的问题。
我的解决方法是添加一个虚拟 iOS 单一视图目标,然后将其指定为单元测试主机应用程序。
这当然会为您的测试代码提供一个 UI带有委托和 window 的应用程序单例。
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!")
}
}