swift - 依赖注入:静态方法和参数
问题描述
我正在尝试将单元测试添加到分层在 Objective-C 库上的 Swift 程序中。我目前的主要问题是找到一种方法来注入使用参数化静态工厂方法创建的依赖项。
例如,以下代码是功能性的,但耐测试:
class Processor {
var service: RegistrationService?
func register(user: String, pass: String) {
let configuration = Configuration(user: user, pass: pass)
service = RegistrationServiceProvider.registrationService(configuration: configuration)
// Do various things with the 'service'
}
}
请注意RegistrationServiceProvider
,RegistrationService
、 和Configuration
都来自 Objective-C 库。
我希望能够做的是提供RegistrationService
在此代码中创建的默认值,并在测试时用我自己的模拟替换它。如果没有使用http://www.danielhall.io/swift-y-dependency-injection-part-twoConfiguration
之类的相当简单的对象。
(我意识到我可以/应该将Configuration
构造推送给调用者,但这并不能解决如何将其提供给默认服务的问题。)
欢迎提出建议和参考。
解决方案
您可以创建 RegistrationService 和 RegistrationServiceProvider 的模拟并将它们注入测试中,使用标准 Type 作为正常调用中的默认类型,如下面的代码(它包括您使用的类的示例版本和一些打印输出以查看什么叫):
class Configuration {
let user: String
let pass: String
init(user: String, pass: String) {
self.user = user
self.pass = pass
}
}
class RegistrationService {
let configuration: Configuration
init(configuration: Configuration) {
self.configuration = configuration
}
}
class RegistrationServiceProvider {
class func registrationService(configuration: Configuration) -> RegistrationService {
print("Provider instantiated service")
return RegistrationService(configuration: configuration)
}
}
class Processor {
var service: RegistrationService?
func register(user: String, pass: String, serviceProvider: RegistrationServiceProvider.Type = RegistrationServiceProvider.self) {
let configuration = Configuration(user: user, pass: pass)
service = serviceProvider.registrationService(configuration: configuration)
// Do various things with the 'service'
}
}
class MockProvider: RegistrationServiceProvider {
override class func registrationService(configuration: Configuration) -> RegistrationService {
print("Mock provider instantiated mock service")
return MockService(configuration: configuration)
}
}
class MockService: RegistrationService {
override init(configuration: Configuration) {
super.init(configuration: configuration)
print("Mock service initialized")
}
}
let processor = Processor()
processor.register(user: "userName", pass: "myPassword") // Provider instantiated service
processor.register(user: "userName", pass: "myPassword", serviceProvider: MockProvider.self) // Mock provider instantiated mock service
推荐阅读
- r - Mac OS XR 错误“ld: framework not found CoreFoundation”
- ios - iOS MVC 中的模型应该包含逻辑代码吗?
- macros - 升级 kentico V11 --> V12 后的宏问题
- r - 如何在R中将多个相似的脚本组合成一个?
- python - 调用函数并非所有函数都使用 argparse 快捷方式
- forms - Spring Boot - 使用@PathVariable 将数据放入更新表单
- python - 如何实现虚拟属性层次结构?
- authentication - 将逻辑应用凭据传递给自定义 SharePoint 客户端 C# 函数应用 SharePoint
- sql - 带有否定 WHERE 条件的 SQL JOIN
- ruby - 在 ActiveAdmin 中根据需要设置字段