ios - 对符合 Swift 协议(protocol)的对象和变量进行单元测试

标签 ios swift unit-testing xctest viper-architecture

我有一个 VIPER 架构设置,正在尝试对线框的实例化进行单元测试。

对于任何不知道 VIPER 是什么的人来说,要理解的关键部分是有 4 个类具有关键职责。线框创建其他 3 个( View 、演示者和交互器)。然后线框将它们适本地连接起来,如下所示:

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

最佳答案

我讨厌自己回答自己的问题,但是:

我必须让每个协议(protocol)都被视为一个类,然后在结果引用运算符上使用 nil 合并来解决这个问题。

protocol LoginInteractorInput : class {

}

func testInitWithNothingShouldInstantiateVIPERStackAndConnectLayers() {
    wireframe = LoginWireframe()       

    XCTAssert(wireframe.modulePresenter === wireframe.moduleInteractor.presenter ? true : false, "Interactor's presenter must be the module's presenter")
}

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

关于ios - 对符合 Swift 协议(protocol)的对象和变量进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32288317/

相关文章:

ios - iOS 中的 NSShadow set() 方法

iphone - 如何使用 ALAssets 库获取视频的绝对路径?

ios - 如果应用程序从任务管理器中被终止,NSUrlSession 是否继续文件传输?

java - 我如何模拟提供使用 JMockit 模拟的类的实例的静态方法?

unit-testing - PHPUnit - 如何在另一个类的方法中模拟该类?

java - 模拟服务方法调用(来自内部 forEach 循环)时抛出 NullPointerException ,实现此模拟的正确方法是什么?

ios - Swift + Storyboard : How to keep strong reference to show segue controller?

swift - HMAC SHA512 在 Swift 3.1 中使用 CommonCrypto

ios - 如何在 swift 3 中将 NSArray 转换为 Swift 数组

swift - UIButton 边框功能仅返回白色边框