[翻译练习] 对视图控制器压入导航栈进行测试

203 阅读2分钟

译自:swiftandpainless.com/testing-pus…


上个月我写的关于使用 Swift 进行测试驱动开发的书终于出版了,我会在本文和接下来的一些博文中介绍这本书撰写过程中的一些心得和体会。

在本文中,我将会展示一种很好的用来测试一个视图控制器是否因为某个事件而被压入导航栈的方法。

假设我们在视图控制器上有一个按钮。当用户点击按钮时,一个新的视图控制器应该被压入导航栈中。我们怎么测试这个呢?

简单!我们可以通过对导航栏控制器进行 Mock 的方式来达到我们的目的,就像接下来这样:

class MockNavigationController: UINavigationController {
  
  var pushedViewController: UIViewController?
  
  override func pushViewController(viewController: UIViewController, animated: Bool) {
    pushedViewController = viewController
    super.pushViewController(viewController, animated: true)
  }
}

确切地说,这是部分 Mock。这里我们建立了一个 UINavigationController 的子类,并且它只重写了父类的一个方法。这个 Mock 操作会在 pushViewController(_:animated:) 被调用时被触发,并且会将传入的视图控制器也就是第一个参数保存下来。

测试代码如下所示:

func testTappingPushButton_PushesDetailViewControllerOntoStack() {
  let viewController = ViewController()
  let navigationController = MockNavigationController(rootViewController: viewController)
  UIApplication.sharedApplication().keyWindow?.rootViewController = navigationController
  
  guard let view = viewController.view as? View else { XCTFail(); return }
  view.button.sendActionsForControlEvents(.TouchUpInside)
  
  XCTAssertTrue(navigationController.pushedViewController is DetailViewController)
}

首先,我们将一个视图控制器设为我们 Mock 导航栏控制器实例的 rootViewController。然后我们将导航栏控制器设为 UIApplication 单例的 keyWindowrootViewController。为了能够将一个视图控制器压入导航栈中,视图控制器的视图必须位于视图层次里,这一步是必须的。

下一步,我们获取按钮并且向它发送 .TouchUpInside 事件。最后我们断言弹出的视图控制器是 DetailViewController 类型的。

你可以在 GitHub 上找到相应的示例代码。

你可以在我的书中找到更多贴近实际的测试例子。当你读这本书时,请别忘了告诉我你对这本书的看法。


如有任何知识产权、版权问题或理论错误,还请指正。
https://juejin.cn/post/6844903529816014862
转载请注明原作者及以上信息。