我的代码库使用设备运动数据来实现特定的功能。我想对它进行单元测试。为此,我需要模拟CMMotionManager,以便可以根据需求操作数据和执行测试用例。有什么办法可以做到这一点吗?
以下函数的回调需要模拟
startDeviceMotionUpdates(to queue: OperationQueue, withHandler handler: @escaping CMDeviceMotionHandler)
有两种简单的方法可以用来嘲笑它;
- 子类
您可以将CMMotionManager
子类化,并重载要模拟的函数。这将允许您在当前使用CMMotionManager
的任何位置注入mock。
class CMMotionManagerMock: CMMotionManager {
override func startDeviceMotionUpdates(to queue: OperationQueue, withHandler handler: @escaping CMDeviceMotionHandler) {
// Mock your desired functionality
}
}
- 协议&扩展
使用协议时,您必须在整个代码库中使用该协议,以便能够在需要时注入mock。这是一个抽象层,如果它只用于测试目的,可能会令人困惑。
protocol DeviceMotionUpdatable {
func startDeviceMotionUpdates(to queue: OperationQueue, withHandler handler: @escaping CMDeviceMotionHandler)
}
extension CMMotionManager: DeviceMotionUpdatable {}
// The mock
class CMMotionManagerMock: DeviceMotionUpdatable {
func startDeviceMotionUpdates(to queue: OperationQueue, withHandler handler: @escaping CMDeviceMotionHandler) {
// Mock your desired functionality
}
}
// Implementation
class Some {
let motionManager: DeviceMotionUpdatable
init(motionManager: DeviceMotionUpdatable = CMMotionManager()) {
self.motionManager = self.motionManager
}
}
// Call site
Some() // Injects the real motion manager
Some(motionManager: CMMotionManagerMock()) // injects the mock motion manager