【发布时间】:2020-12-14 16:15:35
【问题描述】:
我有一个要测试的类方法:
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),
},
}
}
我可以在我的测试中使用 Gpio 类的模拟来为 stepperMotors 属性创建一个模拟(我已经在模拟其他一些测试的构造函数):
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:
但是编译器还在骂我:
另一个更新
在 Taplar 指出如何在演员版本上调用该方法后,错误在后门消失了,这太棒了!
我撞到的下一堵墙是,由于某种原因,现在测试无法再看到我的模拟了,这很奇怪,因为该变量是测试的本地变量。
【问题讨论】:
-
jest 有能力用假方法模拟方法吗?或者即使没有,您也可以尝试替换类实例上的方法(或添加一个),然后尝试更改
this.stepperMotors -
天哪,我喜欢这种方法,那是超级切肉刀!可悲的是它不起作用,因为我使用的是打字稿。我试过了,编译器出错了,因为类中不存在后门属性:|使用这种方法,我也尝试替换原型上的
initalizeMotors方法,但编译器也失败了,因为该方法也是私有的。 -
(yourInstance as any).backdoor = ... -
嗯,尝试了强制转换,但编译器仍在抱怨:|我喜欢在大多数情况下都有打字稿编译器,但在这里非常令人沮丧
标签: javascript typescript unit-testing jestjs