我正在尝试对视图控制器的内存进行单元测试,以查看它们在被关闭时是否正确地初始化。
class SettingsViewControllerTests: XCTestCase {
var controller: SettingsViewController!
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
controller = storyboard.instantiateViewController(withIdentifier: "SettingsViewController")
as? SettingsViewController
//load view hierarchy
_ = controller.view
}
func testLogout() {
let sideMenu = MockSideMenuViewController()
var navController: UINavigationController? = UINavigationController(rootViewController: sideMenu)
sideMenu.show(navController!, sender: nil)
navController?.pushViewController(controller, animated: true)
expect(navController).toNot(beNil())
controller.dismiss(animated: false, completion: nil)
expect(navController).toEventually(beNil(), timeout: 3) // fails
expect(self.controller).toEventually(beNil(), timeout: 3) // fails
}
在应用程序中,我使用segue展示了我的导航控制器+ SettingsViewController。它有一个自身调用dismiss
的方法,但是当我检查控制器实例时,它们仍然存在。在我的视图控制器中,我设置了一条打印语句来检查是否调用了deinit,并在应用程序上执行这些步骤时,它确实被调用了(两个控制器最终都转到nil
)。但是,单元测试不能做到这一点。我想念什么?
答案 0 :(得分:1)
controller
是一个严格控制的属性,因此您的测试将保留它。现在,它仅在随后对setUp()
的调用中被取消初始化。如果您想专门测试controller.deinit
,请在测试中进行controller = nil
。
您可能可以执行以下操作:
var controller: SettingsViewController! // <--- this is a strong ref
func testLogout() {
let sideMenu = MockSideMenuViewController()
// navController is a strong ref, held until the end of the scope; don't expect it to be nil
var navController: UINavigationController? = UINavigationController(rootViewController: sideMenu)
sideMenu.show(navController!, sender: nil)
navController?.pushViewController(controller, animated: true)
// hold a weak ref to your controller and then nil out its reference
weak var weakController = controller
// remove the strong reference
controller = nil
// popping will release the last reference
navController?.popViewController(animated: false)
expect(weakController).to(beNil(),) // succeeds
}
一些注意事项:
navController
是作用域级别的变量。直到函数结束才为零,因此没有理由进行测试或期望。创建它之后,它肯定也不会为零。
UIViewController.dismiss(...)用于消除模态。您的控制器是导航堆栈的一部分。开除不会达到您的期望。
感觉像您期望var navController: UINavigationController?
一样薄弱,但事实并非如此。 weak
的vars和properties应该为Optional
,但为Optional并不意味着weak
。参见Weak References。