在单元测试中使用不可用的初始化器模拟Cocoa对象

thy*_*rel 7 unit-testing mocking ios core-bluetooth swift

我正在使用Swift构建一个iOS应用程序,该应用程序使用Apple的CoreBluetooth框架通过Bluetooth Low Energy与外围设备进行通信.在单元测试实现CBCentralManagerDelegateCBPeripheralDelegate协议的自定义控制器的过程中,我提供了一个来自CBCentralManager测试双子类,以模仿CoreBluetooth API的行为.在适当的时候调用控制器的委托回调.

到目前为止,这一直很好.但是当调用CBPeripheralDelegate回调时,需要传入CBPeripheral.通常,我只是伪造提供我自己的子类的组件或模拟CBPeripheral的实例.

这是捕获:底层Objective-C库中CBPeripheral的指定初始化程序被标记为不可用,这阻止我在伪造的CBCentralManager中实例化CBPeripheral并将其作为参数传递给正在测试的CBPeripheralDelegate.(XCode给我留下了编译错误.)

到目前为止,我已经尝试在我的假子类中提供自定义初始化程序(由于我最终必须调用不可用的指定init,因此无效),用扩展名覆盖初始化程序(显然不允许)并调用选择器(init) )使用Objective-C运行时,我不会给它一个不可用的东西.最后一种方法似乎是最有希望的,但是并没有真正起作用并且让我处理错误类型的非托管对象(我的测试类).

我肯定在这里遇到了障碍,对于任何输入都会非常高兴

  1. 尽管init()不可用,但实例化CBPeripheral

  2. CBPeripheralDelegate进行单元测试的一种方法

thy*_*rel 4

我设法自己解决了这个问题,通过追求 objc 运行时的想法并在 Objective-C 中创建一个对象工厂,该工厂通过其指针调用初始化程序的实现以忽略不可用标记。

有关更多信息,请参阅: http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/ (这在当前的 Swift 中不再起作用,但可以轻松调整)