从情节提要中模拟 UIViewController

Posted

技术标签:

【中文标题】从情节提要中模拟 UIViewController【英文标题】:Mocking UIViewController from storyboard 【发布时间】:2016-09-13 12:26:19 【问题描述】:

我有一个关于在来自情节提要的单元测试中模拟 UIViewController 的问题。我在 setUp() 方法中像这样从情节提要中加载了视图控制器,这很好:

var exampleVC: ExampleViewController!

override func setUp() 
    super.setUp()

    exampleVC = storyboard.instantiateViewControllerWithIdentifier("exampleVC") as! ExampleViewController
    UIApplication.sharedApplication().keyWindow?.rootViewController = exampleVC
    let _ = exampleVC.view

但是,问题是我如何才能模拟/覆盖exampleVC 中的方法。我试图改为创建一个 ExampleViewController 子类并在测试方法中创建模拟类,如下所示:

func testExampleMethod() 
    class ExampleViewControllerMock: ExampleViewController 
        var testMethodWasCalled: Bool = false

        override func testMethod() 
            testMethodWasCalled = true
        
    

    let exampleVCMock = ExampleViewControllerMock()
    exampleVCMock.testMethod()

    XCTAssertTrue(exampleVCMock.testMethodWasCalled)

这种方法在测试中崩溃,因为exampleVCMock 上的视图和其他 IBOutlet 为零,并且在以这种方式实例化视图控制器时不会加载(因此需要从情节提要中实例化 exampleVC)。

所以问题是我如何从情节提要中实例化 exampleVC(以便正确连接插座)但同时能够覆盖方法/为我的单元测试正确创建模拟?

感谢任何建议。

【问题讨论】:

如果你在做 UI 测试,为什么不使用 Xcode 的 UITesting 呢? 这是单元测试,而不是 UI 测试?你是说我应该改为 UI 测试? 我不知道你要测试什么,但它似乎与屏幕渲染有关,所以是的,你应该迁移到 UI 测试 遇到完全相同的问题。你找到解决办法了吗? 【参考方案1】:

乔·本顿!在尝试测试此类场景时,您可以从您在 setUp 上实例化的真实 ViewController 中借用所有 UI 依赖项,并将它们应用到您的模拟 ViewController 中。

例如,如果你有一个 UIButton 和一个 UITableView:

// exampleVC is your real UIViewController loaded on setUp.

mockViewController.loginButton = exampleVC.loginButton
mockViewController.tableView = exampleVC.tableView 

从现在开始,您甚至可以使用这些 UI 元素来验证某些内容。

【讨论】:

以上是关于从情节提要中模拟 UIViewController的主要内容,如果未能解决你的问题,请参考以下文章

UIViewController 内容未显示在情节提要上

如何从情节提要以编程方式加载 UIViewController?

如何以编程方式使用另一个视图中的按钮从情节提要中打开 UIViewController?

未从 UITableViewController 调用 didDeselectRowAtIndexPath 从情节提要添加到 UIViewController

使用情节提要时切换 UIViewController

如何从情节提要属性为 nil 的动态创建的 UIViewController 执行SegueWithIdentifier()