在 Swift 中测试 pushViewController

Posted

技术标签:

【中文标题】在 Swift 中测试 pushViewController【英文标题】:Testing pushViewController in Swift 【发布时间】:2016-11-20 11:05:10 【问题描述】:

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

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

我的方法如下所示:

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

正如我所说。它在模拟器中运行良好,但我想对其进行测试。每次我调用它时,ViewController 都已正确设置。但是Test的结果是完全不同的Controller。

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

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

这怎么可能,我该如何解决?

【问题讨论】:

你想要单元测试还是 UI 测试? 这应该是我路由器的单元测试。这样一切都是正确的,包括呈现的 ViewController。 看起来你的类是 NavigationController 的子类或扩展。你能多分享一点它的界面吗? 不。控制器的实例是相同的。这就是为什么我不明白为什么它不起作用。在 NavigationViewController 中无非是一个基于 String 的 switch 来准备 ViewController,它将被传递给 "navigateToViewController" 方法。 这里我有一个示例项目,其中仅包含出现问题的部分。希望有人可以帮助我解决这个问题。 github.com/Evil-Me/SegueUnitTestApp 【参考方案1】:

更新答案:

使用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。由于这是文件范围,我们需要小心不要让它“渗入”其他测试。所以在setUp重置它:

    override func setUp() 
        super.setUp()
        performSegueIdentifiers = []
        // other set-up
    

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

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

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

【讨论】:

感谢乔恩的回复。我明天早上直接试试这个。到目前为止听起来不错。非常感谢您的帮助。我很感激。 乔恩,你是我的英雄。它就像一个魅力。我现在可以看到执行了什么 segue 并且可以检查它。非常感谢。【参考方案2】:

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

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

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

【讨论】:

我做了这个,控制器没有出现在那里。

以上是关于在 Swift 中测试 pushViewController的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 解决测试驱动开发中的构建错误?

在 Swift 测试驱动开发中对 @ObservableObject 进行单元测试

在 Swift 中测试自定义视图

在 Swift 中测试 pushViewController

在 Swift 单元测试中,我在 App 和单元测试目标之间遇到类转换错误

在 Swift 中使用 OHHTTPStubs 测试请求正文