在 Swift 中测试 pushViewController

Testing pushViewController in Swift

我尝试设置一个路由器以向右导航 Viewcontroller。当我在模拟器中调用它时,它确实工作正常。

但是:当我尝试通过 NavigationController 的 topViewController 或 presentedViewController 属性 测试此转换的结果时,我总是得到每个 Viewcontroller但不是正确的。

我的方法如下所示:

func navigateToViewController(_ viewController: UIViewController, animated: Bool) {
    self.pushViewController(viewController, animated: animated)
}

正如我所说。它在模拟器中工作得很好,但我想测试一下。每次我调用它时 ViewController 都被正确设置。但是测试的结果是一个完全不同的控制器。

当我断言 topViewController 或 presentedViewController 应该是 HomeViewController 时,我总是得到不同的 ViewController 作为结果。

XCTAssertTrue(self.sut.topViewController is HomeViewController,
                   "The TopViewController should be set to the HomeViewController but instead: \(self.sut.topViewController)")

怎么会这样,我该如何解决?

试试这段代码,它会帮助您获取 class 导航控制器的视图控制器堆栈中每个视图控制器的名称

for VC in (self.navigationController?.viewControllers)! {
            print(VC.classForCoder)
        }

因为我不确定您的代码中还有哪些可能已将一些视图控制器添加到导航控制器的视图控制器堆栈中

更新后的答案:

使用https://github.com/jonreid/ViewControllerPresentationSpy

原回答:

似乎没有好的方法来单元测试调用 performSegue 效果 。我们可以做的是记录它是如何被调用的。在测试代​​码中,添加:

fileprivate var performSegueIdentifiers: [String] = []

extension ViewController {
    override open func performSegue(withIdentifier identifier: String, sender: Any?) {
        performSegueIdentifiers.append(identifier)
     }
}

这改变了 ViewController 的 performSegue。我们没有实际执行 segue,而是将标识符附加到 performSegueIdentifiers。由于这是文件范围的,我们需要注意不要让它 "bleed" 进入其他测试。所以在 setUp:

重置它
    override func setUp() {
        super.setUp()
        performSegueIdentifiers = []
        // other set-up
    }

现在您的测试可以调用测试这个数组的内容来确定:

  • 调用次数performSegue
  • 传递给它的 segue 标识符

我们可以相信实际 performSegue 是有效的。我们需要测试的是生产代码是否正确调用了它。