Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何在NEVPNManager中存根连接属性(NEVPNConnection)?_Swift_Nevpnmanager - Fatal编程技术网

Swift 如何在NEVPNManager中存根连接属性(NEVPNConnection)?

Swift 如何在NEVPNManager中存根连接属性(NEVPNConnection)?,swift,nevpnmanager,Swift,Nevpnmanager,我想通过协议扩展现有的NetworkExtension类,以便对我的代码进行单元测试 我首先为NEVPNManager protocol NEVPNManagerProtocol { var connection : ConnectionProtocol { get } // <-- Doesn't work func loadFromPreferences(completionHandler: @escaping (Error?) -> Swift.Void)

我想通过协议扩展现有的
NetworkExtension
类,以便对我的代码进行单元测试

我首先为
NEVPNManager

protocol NEVPNManagerProtocol {
    var connection : ConnectionProtocol { get } // <-- Doesn't work
    func loadFromPreferences(completionHandler: @escaping (Error?) -> Swift.Void)
    func saveToPreferences(completionHandler: ((Error?) -> Swift.Void)?)
}

extension NEVPNManager: NEVPNManagerProtocol {}
在NEVPNManager中,我可以看到我正在确认属性签名,但Xcode不相信我,并声称:

类型“NEVPNManager”不符合协议 “NEVPNManagerProtocol”

它会像这样自动更正它:

extension NEVPNManager: NEVPNManagerProtocol {
    var connection: ConnectionProtocol {
        <#code#>
    }
}

有什么建议吗

模仿这一点很棘手,因为苹果控制着
NEVPNManager
及其
NEVPNConnection
的实例化

您看到的错误是因为您试图重新定义
连接
属性,但您无法这样做
NEVPNManager
已具有类型为
NEVPNConnection
connection
属性

我们可以使用第一个协议(已修改)和两个模拟类的组合来模拟
连接
属性

首先,需要稍微调整协议:

protocol NEVPNManagerProtocol {
    var connection : NEVPNConnection { get } // <-- has to be this type
    func loadFromPreferences(completionHandler: @escaping (Error?) -> Swift.Void)
    func saveToPreferences(completionHandler: ((Error?) -> Swift.Void)?)
}

extension NEVPNManager: NEVPNManagerProtocol {}
最后,我们需要一个返回模拟连接的模拟管理器类。使用模拟管理器是我能够注入模拟连接的唯一方法

模拟管理器符合
NEVPNManagerProtocol
并返回模拟连接对象。(注意:当尝试直接从
NEVPNManager
继承时,我的游乐场在实例化mock时崩溃。)

客户机类必须接受类型为
NEVPNManagerProtocol
而不是
NEVPNManager
的对象,以便我们可以将mock传递给它

class MyClient {
    let manager: NEVPNManagerProtocol
    init(manager: NEVPNManagerProtocol) {
        self.manager = manager
    }
}
在现实生活中,我们可以将真正的经理传递给我们的客户:

let myClient = MyClient(manager: NEVPNManager.shared())
在我们的测试中,我们可以通过模拟:

let myMockedClient = MyClient(manager: MockNEVPNManager())
和调用连接上的方法:

try? myMockedClient.manager.connection.startVPNTunnel()
//prints "MockNEVPNConnection.startVPNTunnel"

太棒了!非常感谢。昨晚,我试图通过子类化来创建mock,结果抛出了与您相同的异常。我没有想到要使用协议和模拟对象的组合。现在我学会了如何模拟系统类。:-)干杯
class MyClient {
    let manager: NEVPNManagerProtocol
    init(manager: NEVPNManagerProtocol) {
        self.manager = manager
    }
}
let myClient = MyClient(manager: NEVPNManager.shared())
let myMockedClient = MyClient(manager: MockNEVPNManager())
try? myMockedClient.manager.connection.startVPNTunnel()
//prints "MockNEVPNConnection.startVPNTunnel"