嘲笑斯威夫特

hpi*_*que 52 unit-testing mocking swift

你如何在Swift中模拟一个对象?

Mirror协议听起来很有希望,但它现在做的并不多.

到目前为止,我发现的唯一方法是子类化并覆盖模拟类的所有方法.这当然不是真正的模仿,远非理想,还有很多工作.

还有其他想法吗?

为什么不是OCMock?

来源:

我可以使用语言桥接功能使用OCMock吗?

是的,但有局限性.如果你很勇敢.截至目前,这是高度实验性的.无法保证OCMock将完全支持Swift.

已知限制:

  • 测试必须用Objective-C编写
  • 应该模拟的对象必须从NSObject继承
  • 没有存根/期望/验证类方法

Dre*_*pre 29

NSHipster涉及Swift中的语言功能,这使得外部模拟库不那么必要:

在Swift中,类可以在函数的定义中声明,允许模拟对象非常自包含.只需声明一个模拟内部类,覆盖和[原文如此]必要的方法:

func testFetchRequestWithMockedManagedObjectContext() {
    class MockNSManagedObjectContext: NSManagedObjectContext {
        override func executeFetchRequest(request: NSFetchRequest!, error: AutoreleasingUnsafePointer<NSError?>) -> [AnyObject]! {
            return [["name": "Johnny Appleseed", "email": "johnny@apple.com"]]
        }
    }

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

在本地范围内创建外部依赖的子类的能力加上XCTestExpectation解决了很多相同的问题OCMock.

OCMock提供的库非常有用的一件事是它的"验证"方法,以确保调用模拟类.可以手动添加它,但自动添加很好.

  • @ hris.to我认为单元测试不应该访问私有方法.理想情况下,您将使用Inversion of Control来注入模拟对象.由于您的代码只会访问该模拟对象上的公共方法,因此私有方法无关紧要.http://stackoverflow.com/questions/3058/what-is-inversion-of-control(编辑:点击输入太快.想添加IoC信息的链接) (4认同)
  • @ hris.to我恭敬地不同意公开内部功能;-)你正在测试的类被设计成一个更大的系统的一部分,所以它所做的一切都会产生一种其他组件可以以某种方式观察到的效果 - 因此不知何故通过测试可观察到.(如果您在外部无法观察到您正在做的事情,那么您为什么要编写代码?!) (2认同)

Mar*_*ark 7

我通过将所有内容包装在协议中来创建模拟类。我手动滚动一个模拟类以符合所讨论的协议,如下所示:

protocol Dog: class {
    var name: String { get }

    func bark()
}

class DogImpl: Dog {
    var name: String

    init(name: String) {
        self.name = name
    }

    func bark() {
        print("Bark!")
    }
}

class DogMock: Dog {
    var name = "Mock Dog"
    var didBark = false

    func bark() {
        didBark = true
    }
}
Run Code Online (Sandbox Code Playgroud)

我将其与依赖项注入结合使用以实现完整的测试范围。这是很多样板,但是到目前为止,这种方法我还没有遇到任何问题。

关于子类模拟,您将遇到final类或类具有非平凡的初始化器的麻烦。