【发布时间】:2016-03-21 12:01:26
【问题描述】:
您好,我正在尝试模拟我用来测试各种视图控制器是否正确调用它的方法的单例。
我有这样声明的单身人士
public class ModelsManager {
static let sharedInstance = ModelsManager()
private init() {}
[...]
}
在使用单例的视图控制器中,它被设置为一个惰性计算属性:
class MyViewController: UIViewController {
lazy var Models = {
return ModelsManager.sharedInstance
}()
[...]
}
我试图在我的 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
}
}
在expect() 断言中我得到Value of type 'ModelsManager' has no member 'flag'
我在这里缺少什么?
编辑
看来我缺少的是ModelsManagerMock.sharedInstance 仍然从超类返回IRModelsManager()。由于static 不能被子类覆盖,我该如何解决这个问题?
【问题讨论】:
-
你是在继承单例吗?如果您尝试将其设置在同一类中而不是子类中,我认为您会有更好的运气。然后,如果您在视图控制器中将其设置为惰性,则不需要在 testSomething() 方法中再次设置它。
-
如果我不设置,那么ViewController将如何使用
ModelsManagerMock呢? -
我不会那样子类化它。您的单例方法返回的是 ModelsManager 的实例,而不是 ModelsManagerMock。如果您需要将其编写为单例,则需要重写单例方法以返回正确的类。在 Obj-C 中,使用实例类型很容易。我会看看是否有办法在 Swift 中做到这一点。
-
如果名为 TEST 的预处理器标志为真,则不将
ModelsManager的init方法设为私有,从而部分解决了此问题。然后我不做vc.Models = mockModelsManager,而是做let mock = ModelsManagerMock(); vc.Models = mock。如果可能的话,我仍在寻找一个编译时解决方案......