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"