在 swift 中将可测试代码与静态方法分派相结合
Combining testable code with static method dispatch in swift
我最近阅读了很多关于 Swift 的运行时,并且对使用静态方法分派优化我的代码越来越感兴趣。这发生在以下方法中:
- 结构方法
- final class 方法,即使用 final 关键字声明为私有或在 final class
中
- 协议扩展中定义的协议方法,但未在协议本身中声明。
问题是,这些情况都不能让我编写可测试的代码,至少不是我现在这样做的方式:注入在单元测试中被模拟替换的协议实体。
那么,是否可以在不放弃静态方法分派的情况下编写可测试的代码,如果可以的话,应该怎么做呢?
谢谢!
泛型就是您要找的。您可以对协议进行抽象,但编译器仍然知道您使用的确切类型,因此不需要动态调度。
protocol Dependency {
func doSomething()
}
struct RealDependency: Dependency {
func doSomething() {
print("I'm doing real work")
}
}
struct MockDependency: Dependency {
func doSomething() {
print("I'm the mock, so I do nothing")
}
}
struct MyApp<D: Dependency> {
let dependency: D
func doSomething() {
dependency.doSomething()
}
}
let myAppReal = MyApp(dependency: RealDependency())
let myAppMock = MyApp(dependency: MockDependency())
myAppReal.doSomething() // Prints "I'm doing real work"
myAppMock.doSomething() // Prints "I'm the mock, so I do nothing"
但是请注意,在 Swift 中,不能保证泛型单态化。所以你 可能 以某种形式的动态调度结束。参见 this link
我最近阅读了很多关于 Swift 的运行时,并且对使用静态方法分派优化我的代码越来越感兴趣。这发生在以下方法中:
- 结构方法
- final class 方法,即使用 final 关键字声明为私有或在 final class 中
- 协议扩展中定义的协议方法,但未在协议本身中声明。
问题是,这些情况都不能让我编写可测试的代码,至少不是我现在这样做的方式:注入在单元测试中被模拟替换的协议实体。
那么,是否可以在不放弃静态方法分派的情况下编写可测试的代码,如果可以的话,应该怎么做呢?
谢谢!
泛型就是您要找的。您可以对协议进行抽象,但编译器仍然知道您使用的确切类型,因此不需要动态调度。
protocol Dependency {
func doSomething()
}
struct RealDependency: Dependency {
func doSomething() {
print("I'm doing real work")
}
}
struct MockDependency: Dependency {
func doSomething() {
print("I'm the mock, so I do nothing")
}
}
struct MyApp<D: Dependency> {
let dependency: D
func doSomething() {
dependency.doSomething()
}
}
let myAppReal = MyApp(dependency: RealDependency())
let myAppMock = MyApp(dependency: MockDependency())
myAppReal.doSomething() // Prints "I'm doing real work"
myAppMock.doSomething() // Prints "I'm the mock, so I do nothing"
但是请注意,在 Swift 中,不能保证泛型单态化。所以你 可能 以某种形式的动态调度结束。参见 this link