У меня есть приложение, построенное с использованием шаблона MVP-C.
В моем HomeFlowCoordinator
я вызываю start, и это вызывает метод showHomeScene
, который устанавливает стек навигации с правильным представлениемконтроллер.
Это выглядело вот так
protocol HomeFlowCoordinatorDelegate: class { }
class HomeFlowCoordinator: Coordinator {
var childCoordinators = [Coordinator]()
let navigationController: UINavigationController
weak var delegate: HomeFlowCoordinatorDelegate?
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
showHomeScene()
}
private func showHomeScene() {
navigationController.setViewControllers([HomeConfigurator().configuredViewController(delegate: self)], animated: false)
}
}
extension HomeFlowCoordinator: HomeSceneDelegate { }
Я принял решение ввести асинхронный вызов для моей службы CompanyService, чтобы я мог получить некоторые удаленные ресурсы, необходимые перед тем, как выполнить рендеринг.представление, но после того, как пользователь вошел в систему.
Поскольку я использую PromiseKit
, введение моей службы изменило вид координатора так:
protocol HomeFlowCoordinatorDelegate: class { }
class HomeFlowCoordinator: Coordinator {
var childCoordinators = [Coordinator]()
let navigationController: UINavigationController
weak var delegate: HomeFlowCoordinatorDelegate?
private lazy var companyService = Dependencies.companyService.inject()
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
showHomeScene()
}
private func showHomeScene() {
companyService.fetch()
.done(on: DispatchQueue.main) { company in
BrandingProvider.shared.configure(branding: company.branding)
}.ensure {
self.navigationController.setViewControllers([HomeConfigurator().configuredViewController(delegate: self)], animated: false)
}.catch { err in
print(err)
}
}
}
extension HomeFlowCoordinator: HomeSceneDelegate { }
extension HomeFlowCoordinator {
struct Dependencies {
static let companyService = Injection<CompanyServiceProtocol>(CompanyService())
}
}
Функционально это работает, однако яу меня есть 2 теста для моего координатора, которые сейчас не выполняются.
Первоначально мой тестовый класс выглядел следующим образом
class HomeFlowCoordinatorTests: XCTestCase {
var sut: HomeFlowCoordinator!
override func setUp() {
super.setUp()
sut = HomeFlowCoordinator(navigationController: UINavigationController())
}
override func tearDown() {
super.tearDown()
sut = nil
}
func test_Start_NavigationControllerIsNotNil() {
sut.start()
XCTAssertFalse(sut.navigationController.viewControllers.isEmpty)
}
func test_ShowHomeScene_HomeSceneIsCorrectClass() {
sut.start()
XCTAssertTrue(sut.navigationController.visibleViewController is HomeViewController)
}
}
extension HomeFlowCoordinatorTests {
class MockHomeFlowCoordinatorDelegate: HomeFlowCoordinatorDelegate { }
}
Я попытался провести рефакторинг тестов следующим образом, но этот тест по-прежнему не проходит
func test_Start_NavigationControllerIsSetWhenCompanyThrows() {
let companyExpectation = expectation(description: "company")
class MockCompanyService: CompanyService {
var companyExpectation: XCTestExpectation!
override func fetch() -> Promise<Company> {
return Promise { seal in
let error = NSError(domain: "", code: 1, userInfo: nil)
companyExpectation.fulfill()
seal.reject(error)
}
}
}
let companyService = MockCompanyService()
HomeFlowCoordinator.Dependencies.companyService.overrideOnce = { companyService }
let sut = HomeFlowCoordinator(navigationController: UINavigationController())
companyService.companyExpectation = companyExpectation
sut.start()
waitForExpectations(timeout: 1) { _ in
XCTAssertFalse(sut.navigationController.viewControllers.isEmpty)
}
}
Я представлял, что при издевательстве над сервисом моей компании и выполнении ожидания блок 1026 * моего обещания должен сработать, и тест должен пройти.