Objective c 如何重写Swift类属性以进行测试
我有一个Swift类,我正在进行单元测试。该类的主要用途是进行HTTP调用。我刚刚使用模拟完成了所有网络请求,但我想确保今后不会忘记模拟未来的请求。在我进行初始模拟时,我将使用的基本URL替换为一个不起作用的URL,但我希望仅在测试时保留该URL。被测试的类如下所示:Objective c 如何重写Swift类属性以进行测试,objective-c,swift,unit-testing,mocking,method-swizzling,Objective C,Swift,Unit Testing,Mocking,Method Swizzling,我有一个Swift类,我正在进行单元测试。该类的主要用途是进行HTTP调用。我刚刚使用模拟完成了所有网络请求,但我想确保今后不会忘记模拟未来的请求。在我进行初始模拟时,我将使用的基本URL替换为一个不起作用的URL,但我希望仅在测试时保留该URL。被测试的类如下所示: public class MyWebServiceWrapper { ... public class var baseURL: String { return "https://api.thes
public class MyWebServiceWrapper {
...
public class var baseURL: String {
return "https://api.thesite.com"
}
...
}
我尝试使用Objective-C类来替换baseURL
的实现,还尝试使用方法swizzling(我让类派生自NSObject
,并用一个方法而不是上面所示的属性替换了baseURL
——我不希望swizzle,特别是因为我不需要该类成为NSObject
子类)
这是我用来执行尝试swizzle的代码,没有效果。对于下面两种尝试的解决方案,我都是这样重写我的测试类的(因为这两种方法似乎都不能很好地处理Swift属性或纯Swift类):
这是我的swizzling尝试(在Swift中)。根据日志,我每次都点击else
语句,以防它有助于了解发生了什么
extension MyWebServiceWrapper {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
if self !== MyWebServiceWrapper.self {
return
}
dispatch_once(&Static.token) {
NSLog("Replacing MyWebServiceWrapper base URL...")
let originalSelector = #selector(baseURLValue)
let swizzledSelector = #selector(networkFreeBaseURL)
guard let klass = object_getClass(self) else {
return
}
let originalMethod = class_getClassMethod(klass, originalSelector)
let swizzledMethod = class_getClassMethod(klass, swizzledSelector)
let didAddMethod = class_addMethod(klass, originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod))
if didAddMethod {
NSLog("MyWebServiceWrapper method added")
class_replaceMethod(klass, swizzledSelector, method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
NSLog("MyWebServiceWrapper implementation replaced")
}
}
}
class func networkFreeBaseURL() -> String {
return "https://tests-shouldnt-hit-the-network.com"
}
}
这就是我尝试使用OCMock(在Objective-C中)替换方法的方式。在配置单元测试期间调用代码
id wrapperMock=OCMClassMock([MyWebServiceWrapper类]);
OCMStub(ClassMethod([wrapperMock baseURLValue])).andReturn(@“https://tests-shouldnt-hit-the-network.com");
要实现从
baseURL
返回无效值的目标,正确的方法是什么?我并不完全满意它(换句话说,我仍然喜欢其他答案),因为它需要修改被测试类的代码,但这就是我最终得到的结果。它完成了任务,并且不容易被非测试代码滥用,因为我使用了覆盖变量internal
public class MyWebServiceWrapper {
...
/// Only use for testing!
internal static var baseURLOverride: String?
public class var baseURL: String {
return baseURLOverride ?? "https://api.thesite.com"
}
...
}
从我的测试配置内部:
@testable
import MyFramework
...
// Inside test configuration
MyWebServiceWrapper.baseURLOverride = "https://tests-shouldnt-hit-the-network.com"
你需要找到另一种方法,否则这是一个解决办法:(你找到解决方案了吗?@denis631我仍然在使用我在下面提供的答案…这似乎不太正确,但你知道…GTD:完成事情:)
@testable
import MyFramework
...
// Inside test configuration
MyWebServiceWrapper.baseURLOverride = "https://tests-shouldnt-hit-the-network.com"