Objective c 如何重写Swift类属性以进行测试

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

我有一个Swift类,我正在进行单元测试。该类的主要用途是进行HTTP调用。我刚刚使用模拟完成了所有网络请求,但我想确保今后不会忘记模拟未来的请求。在我进行初始模拟时,我将使用的基本URL替换为一个不起作用的URL,但我希望仅在测试时保留该URL。被测试的类如下所示:

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"