我有一个要测试的类方法:
setStepResolution(resolution: stepResolution): void {
switch (resolution) {
case stepResolution.FULL_SETUP:
this.stepperMotors.left.ms1Pin.digitalWrite(0)
this.stepperMotors.left.ms2Pin.digitalWrite(0)
this.stepperMotors.left.ms3Pin.digitalWrite(1)
this.stepperMotors.right.ms1Pin.digitalWrite(0)
this.stepperMotors.right.ms2Pin.digitalWrite(0)
this.stepperMotors.right.ms3Pin.digitalWrite(1)
break
case stepResolution.HALF_STEP:
this.stepperMotors.left.ms1Pin.digitalWrite(1)
this.stepperMotors.left.ms2Pin.digitalWrite(0)
this.stepperMotors.left.ms3Pin.digitalWrite(0)
this.stepperMotors.right.ms1Pin.digitalWrite(1)
this.stepperMotors.right.ms2Pin.digitalWrite(0)
this.stepperMotors.right.ms3Pin.digitalWrite(0)
break
这些digitalWrite
调用中的每一个都针对在构造我的类时创建的不同类的实例:
export default class BotController {
private stepperMotors: StepperMotorCollection
constructor() {
this.initalizeMotors()
}
private initalizeMotors(): void {
this.stepperMotors = {
left: {
directionPin: new Gpio(Number(process.env.LEFT_DIRECTION_PIN), { mode: Gpio.OUTPUT }),
stepPin: new Gpio(Number(process.env.LEFT_STEP_PIN), { mode: Gpio.OUTPUT }),
ms1Pin: new Gpio(Number(process.env.LEFT_RESOLUTION_PIN_MS1), { mode: Gpio.OUTPUT }),
ms2Pin: new Gpio(Number(process.env.LEFT_RESOLUTION_PIN_MS2), { mode: Gpio.OUTPUT }),
ms3Pin: new Gpio(Number(process.env.LEFT_RESOLUTION_PIN_MS3), { mode: Gpio.OUTPUT }),
stepsPerMM: Number(process.env.LEFT_STEPS_PER_MM),
swapCoils: Boolean(process.env.LEFT_SWAP_COILS),
},
right: {
directionPin: new Gpio(Number(process.env.RIGHT_DIRECTION_PIN), { mode: Gpio.OUTPUT }),
stepPin: new Gpio(Number(process.env.RIGHT_STEP_PIN), { mode: Gpio.OUTPUT }),
ms1Pin: new Gpio(Number(process.env.RIGHT_RESOLUTION_PIN_MS1), { mode: Gpio.OUTPUT }),
ms2Pin: new Gpio(Number(process.env.RIGHT_RESOLUTION_PIN_MS2), { mode: Gpio.OUTPUT }),
ms3Pin: new Gpio(Number(process.env.RIGHT_RESOLUTION_PIN_MS3), { mode: Gpio.OUTPUT }),
stepsPerMM: Number(process.env.RIGHT_STEPS_PER_MM),
swapCoils: Boolean(process.env.RIGHT_SWAP_COILS),
},
}
}
我可以使用类的模拟stepperMotors
在测试中为属性创建模拟Gpio
(我已经在模拟其他一些测试的构造函数):
test("can change step resolution", () => {
// * The step resolution of the stepper motors can be changed via the code.
// * The settings can be controlled by an enum that denotes each of the possible
// * resolutions.
const mockStepperMotorConfiguration: StepperMotorCollection = {
left: {
directionPin: new pigpio.Gpio(1),
stepPin: new pigpio.Gpio(1),
ms1Pin: new pigpio.Gpio(1),
ms2Pin: new pigpio.Gpio(1),
ms3Pin: new pigpio.Gpio(1),
stepsPerMM: 1,
swapCoils: false,
},
right: {
directionPin: new pigpio.Gpio(1),
stepPin: new pigpio.Gpio(1),
ms1Pin: new pigpio.Gpio(1),
ms2Pin: new pigpio.Gpio(1),
ms3Pin: new pigpio.Gpio(1),
stepsPerMM: 1,
swapCoils: false,
},
}
// ^ To change the resolution to a full step
// * send in the full step enum
newController.setStepResolution(stepResolution.FULL_SETUP)
但是我不能,因为stepperMotor
财产是私有的。
有几种方法可以解决此问题(将属性设置为公共,设置属性的设置为公共方法),但似乎都不可行,因为该属性永远不能在类外部访问,因此我只公开了属性或方法支持测试。
还有另一种进行这种测试的方法吗?我知道开玩笑我可以通过替换原型函数来模拟javascript类中的方法,例如:
BotController.prototype.someMethod = jest.fn()
const controller = new BotController
如果这是我要模拟的类,则可以将属性作为模拟实现传递,例如:
jest.mock("../BotController", () => ({
stepperMotors: mockStepperMotorConfiguration
}))
但是随后,该类中的其他所有内容也将被嘲笑,您将失去这一点。
对我应该如何处理这个有任何想法吗?
我正在尝试Taplar创建后门的方法。
我尝试将控制器实例转换为any
:
But the complier is still yelling at me:
After Taplar pointed out how to call the method on the cast version the errors went away on the back door which is fantastic!
The next wall I smashed into was that now for some reason the test can't see my mock anymore which is weird because the variable is local to the test.
Unless #
hard privacy is used, private properties can be accessed outside a class at runtime, TypeScript access modifiers are applied only at compilation time.
Accessing private members in tests can be considered a reflection.
Visibility can be bypassed with bracket notation, which is the preferable option:
controllerInstance['stepperMotors'] = ...;
Or with Reflect API:
Reflect.set(controllerInstance, 'stepperMotors', ...);
Or by disabling type checks:
(controllerInstance as any).stepperMotors = ...;
由于私有属性是通过原型方法设置的,因此另一种方法是对其进行模拟。如果原始初始化导致不良副作用并需要避免,则适用。BotController.prototype.someMethod = jest.fn()
切勿在Jest中使用它,因为它无法自动清理并交叉污染测试。相反,它可能是:
jest.spyOn(BotController.prototype, 'initalizeMotors').mockImplementation(function (this: BotController) {
this['stepperMotors'] = ...;
});
...
expect(controllerInstance['initalizeMotors']).toHaveBeenCalled();
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句