在 Swift 中模拟单例进行单元测试时遇到问题

Tha*_*nos 5 ios xctest swift swift2

您好,我正在尝试模拟我用来测试各种视图控制器实际上正确调用它的方法的单例之一。

我已经声明了单身人士

public class ModelsManager {
    static let sharedInstance = ModelsManager()
    private init() {}

    [...]
}
Run Code Online (Sandbox Code Playgroud)

在使用单例的视图控制器中,它被设置为一个惰性计算属性,如下所示:

class MyViewController: UIViewController {
    lazy var Models = {
        return ModelsManager.sharedInstance
    }()

    [...]
}
Run Code Online (Sandbox Code Playgroud)

我试图在我的 XCTestCase 中模拟 ModelsManager 单例:

[...]

func testSomething() {
   let vc = MyViewController(nibName: "MyView", bundle: nil)
   var mockModelsManager = ModelsManagerMock.sharedInstance
   vc.Models = mockModelsManager

   [... do something that calls a function in ModelsManager...]

   expect(mockModelsManager.flag) == true // Using Nimble here
}

class ModelsManagerMock: ModelsManager {
    var flag = false

    override func test() {
        flag = true
    }
}
Run Code Online (Sandbox Code Playgroud)

expect()我得到的断言中Value of type 'ModelsManager' has no member 'flag'

我在这里缺少什么?

编辑 看来,我所缺少的是ModelsManagerMock.sharedInstance仍然IRModelsManager()从超类返回。由于static不能被子类覆盖,我该如何解决这个问题?

Mat*_*pen 0

正确的解决方案必须不涉及对单例进行子类化。使用私有 init 方法创建单例会禁止您继承该方法。

如果目标是测试单例的当前功能,为什么要向其添加额外的功能?单例的关键点是应该只有一个。如果您想支持多个,则不应将其设置为单例,即使它只是用于测试。