SwiftyMocky 是一个强类型的框架,用于提供类似 Mockito 的单元测试体验。 该库依赖于 Sourcery,它会扫描您的源代码并为您生成 Mocks Swift 代码!
SwiftyMocky 的想法是自动 mock Swift 协议和协议组合。 主要功能包括
CLI 已移回主 (当前) repo。 此仓库中的 CLI 至少会支持到 5.0.0 版本。
当前版本有几个重大变化。 它删除了已弃用的方法 (可能会造成破坏性更改),并且弃用了在新仓库中使用 CLI 的做法。
SwiftyPrototype 也被提取到单独的库中。 不再有编译标志,因此,如果您依赖于带有 -DMockyCustom
的 SwiftyMocky,则必须切换到 SwiftyPrototype
。
我们认为当前版本是稳定的。 我们正在朝着使用新的Mockfile方向发展,但之前的配置格式仍将受支持。 该库适用于 Swift 4.1、4.2、5.0、5.1.2 和 Sourcery 1.0.x。
虽然从技术上讲可以在 Linux 目标上集成 SwiftyMocky,但目前还没有 Mock 生成功能。 不过,您可以通过 SwiftPM 使用 SwiftyMokcy 运行时,只要您不介意在 mac 机器上生成 mocks。
不需要迁移,您可以像以前一样继续使用 SwiftyMocky。 旧版设置在指南部分中进行了描述。
尽管如此,我们仍然鼓励您尝试新的 CLI 并分享反馈。 我们相信它会让使用和设置 SwiftyMocky 变得更容易。 如果您有现有的设置,请按照此指南安装 CLI 并尝试
> swiftymocky migrate
SwiftyMocky 可通过 CocoaPods 获得。 要安装它,只需将以下行添加到您的 Podfile 中
pod "SwiftyMocky"
从您的项目目录中使用 CLI 工具
# To setup initial Mockfile
% ./Pods/SwiftyMocky/bin/swiftymocky setup
# To generate mocks
% ./Pods/SwiftyMocky/bin/swiftymocky generate
要安装,请将以下内容添加到您的 Cartfile 中
github "MakeAWishFoundation/SwiftyMocky"
然后执行 carthage update
对于Carthage,需要一些额外的步骤
您需要安装 CLI 才能生成 mocks - 请参阅安装
将 SwiftyMocky 添加到您的 Package.swift 依赖项中
dependencies: [
.package(url: "https://github.com/MakeAWishFoundation/SwiftyMocky", from: "4.2.0"),
]
您需要安装 CLI 才能生成 mocks - 请参阅安装
注意: 作为单元测试工具和原型框架的 SwiftyMocky 集成示例,请访问此处:https://github.com/MakeAWishFoundation/SM-Integration-Tests
> brew install mint
> mint install MakeAWishFoundation/SwiftyMocky
> marathon install MakeAWishFoundation/SwiftyMocky
Make:
从 https://github.com/MakeAWishFoundation/SwiftyMockyCLI 克隆,并在根目录中运行 make
。
注解您的协议,使其采用 AutoMockable
协议,或者在源代码中协议定义上方添加注解注释。
Mocks 是从您的项目根目录生成,基于 Mockfile 中的配置。
> path/to/swiftymocky setup # if you don't have a Mockfile yet
> path/to/swiftymocky doctor # validate your setup
> path/to/swiftymocky generate # generate mocks
如果您不想迁移到我们的 CLI 并且更喜欢使用“原始” Sourcery,请参考文档中的此部分。
在您的项目中的某个位置创建一个“虚拟”协议,例如:protocol AutoMockable { }
让您想要实际 mock 的每个协议都采用它。
protocol ToBeMocked: AutoMockable {
// ...
}
或者,使用 sourcery 注解标记要 mock 的协议,如下所示
//sourcery: AutoMockable
protocol ToBeMocked {
// ...
}
或者将其用于协议组合
typealias ToBeMocked = OneProtocol & TwoProtocols & AutoMockable
源目录中具有此注解的每个协议都将被添加到 Mock.generated.swift
中
所有 mocks 都有 given 方法 (既可以作为实例方法访问,也可以作为全局函数访问),它具有易于使用的语法,允许指定给定方法 (基于指定的属性) 的返回值。
所有协议方法都被很好地放入 Given 中,并具有匹配的签名。 这允许使用自动完成功能 (只需键入 .
) 即可查看所有 mock 的协议方法,并指定它们的返回值。
所有方法属性都包装为 Parameter 枚举,允许在 any
和 value
之间进行选择,从而为 mock 行为提供了极大的灵活性。 请考虑以下情况
Given(mock, .surname(for name: .value("Johnny"), willReturn: "Bravo"))
Given(mock, .surname(for name: .any, willReturn: "Kowalsky"))
print(mock.surname(for: "Johny")) // Bravo
print(mock.surname(for: "Mathew")) // Kowalsky
print(mock.surname(for: "Joanna")) // Kowalsky
在 3.0 版本中,我们引入了序列和策略,以便更好地控制 mock 行为。
Given(mock, .surname(for name: .any, willReturn: "Bravo", "Kowalsky", "Nguyen"))
print(mock.surname(for: "Johny")) // Bravo
print(mock.surname(for: "Johny")) // Kowalsky
print(mock.surname(for: "Johny")) // Nguyen
print(mock.surname(for: "Johny")) // and again Bravo
// ...
有关更多详细信息,请参阅完整的文档。
所有 mocks 都有 verify 方法 (既可以作为实例方法访问,也可以作为全局函数访问),它具有易于使用的语法,允许验证是否在 mock 上调用了某个方法,以及调用了多少次。 它还提供了一种方便的方式来指定方法属性是否重要 (以及哪些属性重要)。
所有协议方法都被很好地放入 Verify 中,并具有匹配的签名。 这允许使用自动完成功能 (只需键入 .
) 即可查看所有 mock 的协议方法,并指定我们要验证哪个方法。
所有方法属性都包装为 Parameter 枚举,允许在 any
、value
和 matching
之间进行选择,从而为测试提供了极大的灵活性。 请考虑以下情况
// inject mock to sut. Every time sut saves user data, it should trigger storage storeUser method
sut.usersStorage = mockStorage
sut.saveUser(name: "Johny", surname: "Bravo")
sut.saveUser(name: "Johny", surname: "Cage")
sut.saveUser(name: "Jon", surname: "Snow")
// check if Jon Snow was stored at least one time
Verify(mockStorage, .storeUser(name: .value("Jon"), surname: .value("Snow")))
// storeUser method should be triggered 3 times in total, regardless of attributes values
Verify(mockStorage, 3, .storeUser(name: .any, surname: .any))
// storeUser method should be triggered 2 times with name Johny
Verify(mockStorage, 2, .storeUser(name: .value("Johny"), surname: .any))
// storeUser method should be triggered at least 2 times with name longer than 3
Verify(mockStorage, .moreOrEqual(to: 2), .storeUser(name: .matching({ $0.count > 3 }), surname: .any))
对于 Verify,您可以使用 Count 来指定您期望触发多少次。 Count 可以定义为显式值,如 1
、2
等,或者以更具描述性和灵活性的方式定义,如 .never
、more(than: 1)
等。
从 SwiftyMocky 3.0 开始,也可以在属性上使用 Given
并执行 Verify
,具体取决于它是 get 还是 set
mock.name = "Danny"
mock.name = "Joanna"
print(mock.name)
// Verify getter:
Verify(mock, 1, .name)
// Verify setter:
Verify(mock, 2, .name(set: .any))
Verify(mock, 1, .name(set: .value("Danny")))
Verify(mock, .never, .name(set: .value("Bishop")))
所有 mocks 都有 perform 方法 (既可以作为实例方法访问,也可以作为全局函数访问),它具有易于使用的语法,允许指定在调用桩方法时将执行的闭包。
它使用与 given 相同的参数包装功能,因此您可以为不同的属性集指定不同的 Perform 情况。
这在处理基于完成块的方法时非常方便。
示例
// Perform allows to execute given closure, with all the method parameters, as soon as it is being called
Perform(mock, .methodThatTakesCompletionBlock(completion: .any, perform: { completion in
completion(true,nil)
}))
完整的文档可在此处获得,也可以通过 *docs* 目录获得。
指南 - 目录
变更日志可在此处获得
有关更多示例,请查看我们的示例项目,或指南中的示例部分。
要运行示例项目,请克隆 repo,并首先从 Example 目录运行 pod install
。
要触发 mocks 生成,请从根目录运行 rake mock
或 swiftymocky generate
(如果您安装了 CLI)。
SwiftyMocky 在 MIT 许可证下可用。 有关更多信息,请参阅LICENSE文件。