Когда запускается действие, mockNavigationController возвращает текущий viewController, а не выдвигается - PullRequest
0 голосов
/ 18 апреля 2019

Я изучаю TTD, и у меня проблема с контроллером навигации в модульном тестировании. Когда я пытаюсь протолкнуть Detail View Controller через стек навигации (pushViewController (ViewController, animated :)) с моим фиктивным контроллером, в тестовой функции push не выполняется (она выполняется только в первый раз, когда инициализируется навигационный контроллер). На симуляторе iPhone приложение работает корректно. В коде mockNavigationController есть значение pushVC, которое изменяется при выполнении pushViewController. Когда пользователь нажимает на ячейку, dataProvider (делегат и источник данных для tableCell) публикует уведомление в ViewController (sut), в котором реализован метод showDetails.

Я бы попробовал взять topViewController из navigationController: sut.navigationController? .topViewController - это возврат sut ViewController. Попробуйте не инициализировать навигационный контроллер в тесте. sut.navigationController? .topViewController - возвращается ноль.

Это начало XCTestCase

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()
    }

Эта тестовая функция

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

@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

extension EatersListViewControllerTests {
    class MockNavigationController: UINavigationController {

        var pushedVC: UIViewController?

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

Я ожидал, что XCTAssert будет работать правильно, но каждый раз, когда тест не проходил в строке XCTFail (). Я думаю, что где-то ошибка, и здесь не знаю.

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

Нужна помощь с кодом, где я не прав. Спасибо за чтение.

1 Ответ

0 голосов
/ 19 апреля 2019

Привет @ Александр , добро пожаловать в StackOverflow.100

Вы говорите, что dataProvider - это .dataSource и .delegate для UITableView в тестируемом контроллере вашего представления, и именно он отвечает за запуск навигации.

Вы уверены, что в тестах dataProvider фактически установлен как .dataSource и .delegate?Если это не так, код запуска навигации никогда не будет вызван.

Вы можете использовать точки останова для проверки двух вещей:

  1. Если ваш метод showDetails называется
  2. Если метод pushViewController(_:, animated:) в вашем MockNavigationController называется

Я предполагаю, что один из них не вызван, и это может указать вам на причину вашей проблемы.

Если вы позволите мне, несколько дополнительных слов:

  • Я бы рекомендовал использовать шаблон NavigationDelegate для проверки этого поведения.Это упростит вам задачу, избавив от необходимости возиться с UIApplication.
  • . Лучше использовать _ = sut.view или sut.beginAppearanceTransition(true, animated: false) для запуска настройки представления контроллера представления в тестах
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...