3

I have a VIPER architecture setup and am trying to unit test the instantiation of the wireframe.

For anyone who doesn't know what VIPER is, the key parts to understand are that there is are 4 classes that that have key responsibilities. The wireframe creates the other 3 (the view, presenter, and interactor). The wireframe then connects them appropriately like below:

                              Wireframe
                                  ^
                                  |
                                  v
                     View <-> Presenter <-> Interactor

So I am creating the unit tests in Swift, and am having difficulty making sure these connections are setup. Note, the code itself works, the asserts in the unit tests are the problem.

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

Neither of these two asserts compiles correctly.

For the XCTAssertEqual this error occurs

Cannot find an overload for 'XCTAssertEqual' that accepts an argument list of type '(LoginPresenter, LoginInteractorOutput, String)'

For the XCTAssert (or XCTAssertTrue), this error occurs

Cannot invoke 'XCTAssert' with an argument list of type '(Bool, String)'

For completeness and because someone may find the code useful:

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

2 回答 2

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

这确保模块演示者指向与模块交互者的演示者相同的对象。

于 2015-09-07T21:47:10.157 回答
0

据编译器所知,您正在尝试将LoginPresenter(从 继承相等性的具体类NSObject)与LoginInteractorOutput- 一个似乎(来源会有所帮助)不扩展的接口进行比较Equatable。所以它不知道如何比较这两者。

可能的解决方案:

  • 强制转换LoginPresenter(不好)
  • 通过实现让你LoginInteractorOutput继承Equatablefunc ==(las: LoginInteractorOutput, hrs: LoginInteractorOutput) -> Bool
于 2015-08-30T18:53:53.620 回答