Модульное тестирование объекта и переменной, соответствующей протоколу в Swift
У меня есть настройка архитектуры VIPER, и я пытаюсь выполнить модульное тестирование создания каркаса.
Для тех, кто не знает, что такое VIPER, необходимо понять, что есть 4 класса, которые имеют ключевые обязанности. Каркас создает остальные 3 (вид, презентатор и интерактор). Каркас соединяет их соответствующим образом, как показано ниже:
Wireframe
^
|
v
View <-> Presenter <-> Interactor
Поэтому я создаю модульные тесты в Swift и испытываю трудности с установкой этих соединений. Обратите внимание, сам код работает, утверждения в модульных тестах являются проблемой.
func testInitWithNothingShouldInstantiateVIPERStackAndConnectLayers() {
wireframe = LoginWireframe()
XCTAssertEqual(wireframe.modulePresenter, wireframe.moduleInteractor.presenter, "Interactor's presenter must be the module's presenter")
XCTAssert(wireframe.modulePresenter === wireframe.moduleInteractor.presenter, "Interactor's presenter must be the module's presenter")
}
Ни один из этих двух утверждений не компилируется правильно.
Для XCTAssertEqual эта ошибка происходит
Cannot find an overload for 'XCTAssertEqual' that accepts an argument list of type '(LoginPresenter, LoginInteractorOutput, String)'
Для XCTAssert (или XCTAssertTrue) эта ошибка происходит
Cannot invoke 'XCTAssert' with an argument list of type '(Bool, String)'
Для полноты и потому, что кто-то может найти код полезным:
//LoginWireframe.swift
class LoginWireframe: NSObject, LoginWireframeInterface {
lazy var moduleInteractor = LoginInteractor()
lazy var modulePresenter = LoginPresenter()
lazy var moduleView = LoginView()
lazy var presenter : LoginRouting = self.modulePresenter
override init() {
super.init()
let i = moduleInteractor
let p = modulePresenter
let v = moduleView
i.presenter = p
p.interactor = i
p.view = v
p.wireframe = self
v.presenter = p
presenter = p
}
//LoginInteractor.swift
class LoginInteractor: NSObject, LoginInteractorInput {
lazy var presenter : LoginInteractorOutput = LoginPresenter()
}
//LoginPresenter.swift
class LoginPresenter : NSObject, LoginInteractorOutput, LoginPresenterInterface, LoginRouting {
lazy var interactor : LoginInteractorInput = LoginInteractor()
lazy var view : LoginViewInterface = LoginView()
lazy var wireframe : LoginWireframeInterface = LoginWireframe()
}
//LoginView.swift
class LoginView : UIViewController, LoginViewInterface {
lazy var presenter : LoginPresenterInterface = LoginPresenter()
}
2 ответа
Я ненавижу быть парнем, который отвечает на его собственные вопросы, но:
Я должен был сделать каждый протокол классом, а затем использовать нулевое слияние на операторе ссылки на результат, чтобы это сработало.
protocol LoginInteractorInput : class {
}
func testInitWithNothingShouldInstantiateVIPERStackAndConnectLayers() {
wireframe = LoginWireframe()
XCTAssert(wireframe.modulePresenter === wireframe.moduleInteractor.presenter ? true : false, "Interactor's presenter must be the module's presenter")
}
Это гарантирует, что презентатор модулей указывает на тот же объект, что и презентатор модуля.
Насколько компилятор знает, что вы пытаетесь сравнить LoginPresenter
(конкретный класс, наследующий равенство от NSObject
) с LoginInteractorOutput
- интерфейс, который, кажется (источники могут помочь), не расширяется Equatable
, Поэтому он не знает, как сравнить эти два.
Возможные решения:
- применение силы
LoginPresenter
(не хорошо) - Сделать вас
LoginInteractorOutput
унаследоватьEquatable
осуществляяfunc ==(las: LoginInteractorOutput, hrs: LoginInteractorOutput) -> Bool