首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当触发操作时,mockNavigationController返回当前的viewController,而不是按下

当触发操作时,mockNavigationController返回当前的viewController,而不是按下
EN

Stack Overflow用户
提问于 2019-04-18 09:33:06
回答 1查看 597关注 0票数 0

我学习TTD,在单元测试中导航控制器有问题.当我试图通过我的模拟控制器通过导航堆栈(pushViewController(ViewController,动画:))推送详细视图控制器时,在测试推函数中不执行(它只是第一次执行,当navigationController初始化时)。在模拟iPhone上,应用程序工作正常。在代码中,mockNavigationController有值pushedVC,这在pushViewController执行时会发生变化。当用户点击单元格时,dataProvider (委托和dataSource for tableCell)将通知发送给ViewController (sut),实现了showDetails方法。

我试着把topViewController从navigationController: sut.navigationController?.topViewController -它是返回sut ViewController。不要在测试中初始化navigationController。sut.navigationController?.topViewController -这是零回报。

XCTestCase的开始

代码语言:javascript
运行
复制
var sut: EatersListViewController!

    override func setUp() {
        super.setUp()

        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyBoard.instantiateViewController(withIdentifier: String(describing: EatersListViewController.self))
        sut = vc as? EatersListViewController

        sut.loadViewIfNeeded()
    }

这个测试函数

代码语言:javascript
运行
复制
func testSelectedRowPushedDetailVC() {
        let mockNavigationController = MockNavigationController(rootViewController: sut)
        UIApplication.shared.keyWindow?.rootViewController = mockNavigationController

        let eater1 = Eater(name: "Foo")
        sut.dataProvider.manager!.addEater(eater: eater1)

        sut.loadViewIfNeeded()

        sut.tableView.delegate?.tableView?(sut.tableView, didSelectRowAt: IndexPath(row: 0, section: 0))

        guard let detailEaterVC = mockNavigationController.pushedVC as? DetailEaterViewController else {
            XCTFail()
            return
        }
        detailEaterVC.loadViewIfNeeded()

        XCTAssertNotNil(detailEaterVC.eaterNameLabel)
        XCTAssertEqual(detailEaterVC.eaterData, eater1)
}

这个函数来自ViewController

代码语言:javascript
运行
复制
@objc func showDetails(withNotification notification: Notification) {
        guard
            let userInfo = notification.userInfo,
            let eater = userInfo["eater"] as? Eater,
            let detailEaterVC = storyboard?.instantiateViewController(withIdentifier: String(describing: DetailEaterViewController.self)) as? DetailEaterViewController else { return }
        detailEaterVC.eaterData = eater
        navigationController?.pushViewController(detailEaterVC, animated: true)
}

和MockNavigationController

代码语言:javascript
运行
复制
extension EatersListViewControllerTests {
    class MockNavigationController: UINavigationController {

        var pushedVC: UIViewController?

        override func pushViewController(_ viewController: UIViewController, animated: Bool) {
            pushedVC = viewController
            super.pushViewController(viewController, animated: animated)
        }
    }
}

我原以为XCTAssert工作正常,但每次XCTFail()行测试都失败。我想是哪里出了差错,我不知道。

代码语言:javascript
运行
复制
XCTAssertNotNil(detailEaterVC.eaterNameLabel)
XCTAssertEqual(detailEaterVC.eaterData, eater1)

在代码方面需要帮助,我错了。感谢您的阅读。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-19 08:34:35

嗨,@Alexander,欢迎来到StackOverflow。

您说dataProvider是正在测试的视图控制器中的UITableView.dataSource.delegate,它负责启动导航。

您确定在测试中dataProvider实际上被设置为.dataSource.delegate吗?如果不是这样,那么启动导航的代码将永远不会被调用。

您可以使用断点来验证两件事:

  1. 如果您的showDetails方法被调用
  2. 如果您的pushViewController(_:, animated:)方法在MockNavigationController中被调用

我猜其中一个没有被调用,这可能会指出你的问题的原因。

如果你允许的话,再多说几句:

  • 我建议使用 pattern来测试这种行为。通过消除对UIApplication的修改,它将使您的操作变得更简单。
  • 最好在测试中使用_ = sut.viewsut.beginAppearanceTransition(true, animated: false)来触发视图控制器视图的设置
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55743142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档