【发布时间】:2020-08-21 22:41:35
【问题描述】:
如何模拟我正在用 jest 测试的类之一的依赖关系?
我有一个使用 pigpio 模块的类
// a trimmed down version of the class and method I'm writing a test for
import { Gpio } from "pigpio"
export default class BotController {
private initializePenActuator(): void {
this.penPause = Number(process.env.PEN_PAUSE_DELAY_IN_MILLISECONDS)
this.penActuator = new Gpio(Number(process.env.PEN_ACTUATOR_PIN))
}
async setPenDirection(direction: penDirection, toggleAfterDelay?: boolean): Promise<void> {
return new Promise((resolve, reject) => {
this.penActuator.digitalWrite(direction) // the call I want to mock
if (!toggleAfterDelay) {
resolve()
}
setTimeout(() => {
resolve()
}, this.penPause)
})
}
}
我正在尝试为它编写以下测试:
test("can actuate with a delay", async () => {
// * actuate pen with a delay
const start: Date = new Date()
await controller.setPenDirection(penDirection.UP, true)
const end: Date = new Date()
const duration = end.getTime() - start.getTime()
// * confirm that the async call was delayed for the correct number of MS
expect(duration).toBeGreaterThanOrEqual(Number(process.env.PEN_PAUSE_DELAY_IN_MILLISECONDS))
})
但我不确定如何为 digitalWrite 的 pigpio 方法调用编写模拟。
我知道我可以创建一个类的模拟:
jest.mock("pigpio", () => {
return class {
digitalWrite(value) {}
}
})
但这会假设我在测试中直接调用 pigpio 类,而不是通过不同的类(对吗?)。
我一直在尝试阅读有关如何正确执行此操作的文档,但我似乎无法从示例中解析解决方案。如果不是很明显,我仍然在测试中。
我将如何模拟 pigpio 以便我可以测试我的班级的方法?
另外,如果您有指向我应该查看的文档中该位置的链接,我将不胜感激。我不知道我是否误解了我阅读的文档,或者我只是没有在开玩笑的文档中找到正确的位置:|
更新
在查看 Estus 指出的文档中的自动模拟示例后,我看到了如果类是模块的默认导出,则如何模拟该类的示例。
https://jestjs.io/docs/en/es6-class-mocks#automatic-mock
但如果类是模块的默认导出,则此示例有效。就我而言,该类不是默认导出:
如果我尝试只模拟模块,我会收到错误:
如果我尝试为模块模拟 Gpio 类,我仍然会收到错误:
而且我似乎无法在文档中找到正确执行此操作的示例:/
另一个更新
我还尝试为Gpio 类创建一个模拟函数,模拟pigpio 模块并为该模拟提供一个使用Gpio 模拟的实现,但它仍然不起作用:
【问题讨论】:
-
但这会假设我在测试中直接调用 pigpio 类,而不是通过其他类 - 不,模拟你的东西是没有意义的直接在测试中使用。 jest.mock 影响在当前测试套件中导入 pigpio 的所有模块。另见jestjs.io/docs/en/es6-class-mocks#automatic-mock
-
啊!!我在文档中看到了这个示例,但并没有完全理解实现(选择的变量名让我感到震惊),但现在看它我明白了。感谢您指出这部分文档。一旦我今天开始工作,我将更正我的规范并发布答案。谢谢!
-
@EstusFlask 我尝试实现该示例,但文档是针对模块的默认导出是您要模拟的类时编写的。我认为这是文档扔给我的地方。我不确定如何模拟一个不是模块默认导出的类。我用我尝试过的内容更新了我的帖子。有什么想法吗?
-
您错过了 jest.mock 的
__esModule: true,您需要它来命名导出。没有它,一个 mock 被视为 CommonJS 模块,它转换为 ESM 默认导出。见jestjs.io/docs/en/… -
很高兴它有帮助。
标签: typescript unit-testing mocking jestjs