MockNStub 7.0.0

MockNStub 7.0.0

Menno Lovink 维护。



 
依赖关系
InjectableLoggers~> 2
ArrayPlusTuple~> 2
 

MockNStub 7.0.0

  • 作者
  • mennolovink

Mock 'N Stub

Version Platform License

完成 Swift 协议和类的 Mocking 和 Stubbing。

示例

要查看示例项目,请在您的终端中运行以下命令

pod try MockNStub

设置

只需将

import MockNStub

添加到您需要创建模拟和存根的文件中。

所有模拟都是存根

所有创建的模拟都遵循 Mocking 协议,并且因为 Mocking 遵循 Stubbing 协议,所以所有创建的模拟也可以自动用作存根。

当您发现确实需要显式存根支持 Mocking 时,您需要做的就是将其从 Stubbing 改为 Mocking

类和协议的模拟/存根共享完全相同的接口

MockNStub 中的实现完全基于协议。这允许类和协议模拟(以及存根)的接口完全相同。所有显式存根都遵循 Stubbing,所有模拟都遵循 Mocking。无需从此库中继承具体的类型。

存根

创建存根

使用函数名

class UITableViewDataSourceStub: Stubbing, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return didCallFunction(withArguments: tableView, section)
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return didCallFunction(withArguments: tableView, indexPath)
    }
}

注意

  • 无需手动提供函数名。

向存根添加返回值

可以添加任意数量的返回值,如果在同一签名下提供了它们,则返回最后一次提供的值。

使用函数名

考虑

let stub = UITableViewDataSourceStub()

您可以添加存根值如下

stub.given("tableView(_:numberOfRowsInSection:)", willReturn: 0)
stub.given("tableView(_:cellForRowAt:)", willReturn: UITableViewCell())

或者,当需要更具体时,如下所示

stub.given("tableView(_:numberOfRowsInSection:)"), withArgumentsThatMatch: ArgumentMatcher(matcher: { (args: (UITableView, Int)) -> Bool in
	return args.0 === expectedTableView && args.1 == 2
}), willReturn: 42)

注意

  • 如果参数类型不正确,则参数匹配器不会匹配。

模拟

创建模拟

使用函数名

class UITableViewDataSourceMock: NSObject, Mocking, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return didCallFunction(withArguments: tableView, section)
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return didCallFunction(withArguments: tableView, indexPath)
    }
}

创建期望

使用函数名

let mock = UITableViewDataSourceMock()

您可以添加期望如下

mock.expect(callToFunction: "tableView(_:cellForRowAt:)")
mock.expect(callToFunction: "tableView(_:numberOfRowsInSection:)")

或者,当需要更具体时,如下所示

mock.expect(callToFunction: "tableView(_:numberOfRowsInSection:)", withArgumentsThatMatch: ArgumentMatcher(matcher: { (args: (UITableView, Int)) -> Bool in
	return args.0 === tableView && args.1 == 42                        
}))

也可以期望调用精确次数

mock.expect(.exactly(amount: 42), callsToFunction: "tableView(_:cellForRowAt:)")

mock.expect(.exactly(amount: 42), callsToFunction: "tableView(_:numberOfRowsInSection:)", withArgumentsThatMatch: ArgumentMatcher(matcher: { (args: (UITableView, Int)) -> Bool in
	return args.0 === tableView && args.1 == 42                        
}))

验证

无论方法的识别方式如何

mock.verify()

注意

  • 如果有一个或多个期望未被满足,这将导致 XCT 失败。

属性

模拟和存根属性与预期一致。

使用函数名

var title: String {
    get {
        return didCallFunction()
    }
    set {
        didCallFunction(withArguments: newValue)
    }
}

注意

  • 任何属性的这种 get set 模式都是相同的。

didCall() 的默认返回值

MockingStubbing 协议中都有很多针对 didCall 方法的实现。由于 Swift 对类型推断的支持,在编译时将使用正确的方法。例如,当调用 return didCallFunction() 时,将使用非空的 didCallFunction() 实现人员。更有趣的是,当在返回符合 ProvidingDefaultStubValue 的值的函数中调用 return didCallFunction() 时,不需要解开 didCallFunction 的结果,因为默认值已知(并通过默认协议实现提供)。注意:这些默认存根值只有在没有通过 given... 方法提供其他值时才会提供。

不要过于担心以上解释,简而言之:您的 IDE 将始终为您提供可用的最佳选择。

当需要返回不遵守 ProvidingDefaultStubValue 的类型时。编译器不会建议(并允许)返回非可选值的 didCall.. 版本。在这种情况下,你可以做以下三件事:

  • 使该类型遵守 ProvidingDefaultStubValue
    • 如果你是为 Apple 库中的类型这样做,对这个仓库中包含此扩展的 pull request 会非常感激。
  • 手动提供默认值,以防提供 nil: return didCallFunction() ?? MyType()
  • 强制解包 didCall 提供的返回值
    • 在这种情况下,你确实想使用 given.. 方法确保存在一个值。
      • 如果没有这样做,你的测试在调用模拟或伪造的方法时将崩溃。
      • 然而,任何对 nil 值的强制解包在它发生之前都是已知的,并将导致详细的诊断记录到控制台,显示了预期发生的事情和实际发生的事情:Screenshot Missing

目前遵守 ProvidingDefaultStubValue 的类型

  • Swift 标准库中的大多数类型
  • UIKit 中最常用的类型
  • CoreGraphics 中最常用的类型
  • 所有继承自 NSObject 的类型
    • 免责声明;这些子类确实需要遵守 Liskov 替换原则,简单来说:不要在它们的 init() 中有 fatalError() 或类似的内容

这里 是所有目前遵守 ProvidingDefaultStubValue 的类型的概览

定义函数 ID

通过让你的模拟和代理遵守 DefiningFunctionID 来减少由拼写错误引起的错误的一种方式

遵守 DefiningFunctionID 的方式如下

extension UITableViewStub : DefiningFunctionID {
    typealias FunctionID = FuncID
    
    enum FuncID: String {
        case numberOfRows
        case cellForRowAt
    }
}

注意:上面的例子是为代理做的,但同样适用于模拟

遵守 DefiningFunctionID 将解锁下述范围的模拟和代理方法

didCallFunction(withID: .numberOfRows)
mock.expect(callToFunctionWithID: .numberOfRows)

还有更多内容要来..

计划的功能

可以在 路线图 中查看。

还有什么遗漏的吗?

创建一个 功能请求,它很可能会被选中。

安装

MockNStub 通过 CocoaPods 提供。要安装它,只需将以下行添加到你的 Podfile 中

pod 'MockNStub'

许可

MockNStub 在 MIT 许可下提供。有关更多信息,请参阅 LICENSE 文件。