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

时间:2016-03-09 17:12:30

标签: ios swift unit-testing mocking core-bluetooth

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

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

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

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

我肯定在这里遇到了障碍,对于

的任何输入都会非常高兴
    尽管init()不可用,
  1. 实例化 CBPeripheral

  2. 单元测试的不同方法 CBPeripheralDelegate

1 个答案:

答案 0 :(得分:2)

我设法通过追求objc-runtime的想法并在Objective-C中创建一个Object Factory来解决问题,它通过指针调用初始化程序的实现来忽略不可用的标记。

有关详细信息,请参阅: http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/ (这在当前的Swift中不再起作用,但可以很容易地进行调整)