javascript - 如何用 Sinon JS 测试异步功能?
问题描述
下面是我想要实现的一个最小示例:我想测试fn3()
异步函数是否fn2()
解析(调用时fn1
)是否被调用。但是我以某种方式未能使用sinon
stub 语法做到这一点。我想知道我误解了什么。
// System Under Test
export function fn1() {
fn2().then(() => {
fn3();
});
}
export async function fn2() {
return new Promise((resolve, reject) => {
// expensive work
resolve();
});
}
export function fn3() {
console.log("fn3");
}
// Test
import * as Page from "xxx";
it("test async", () => {
// stub this async to isolate the SUT
sinon.stub(Page, "fn2").resolves();
const stub = sinon.stub(Page, "fn3");
Page.fn1();
sinon.assert.calledOnce(stub);
});
/*
AssertError: expected fn3 to be called once but was called 0 times
276 | Page.fn1();
277 |
> 278 | sinon.assert.calledOnce(stub);
| ^
279 | });
280 | });
at Object.fail (node_modules/sinon/lib/sinon/assert.js:107:21)
at failAssertion (node_modules/sinon/lib/sinon/assert.js:66:16)
at Object.calledOnce (node_modules/sinon/lib/sinon/assert.js:92:13)
at Object.<anonymous> (src/test.test.tsx:278:22)
*/
解决方案
正如@jonrsharpe 建议的那样,您sinon.assert.calledOnce(stub);
将在fn2
内部的承诺Page.fn1
被解决(即被.then(() => { fn3(); })
调用)之前被调用,基于JavaScript“单线程,事件循环”性质。这是一篇供参考的文章:https ://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke 。
您可以尝试将代码更改为:
...
return Page.fn1().then(() => {
sinon.assert.calledOnce(stub);
});
...
或者
it("test async", async () => {
// stub this async to isolate the SUT
sinon.stub(Page, "fn2").resolves();
const stub = sinon.stub(Page, "fn3");
await Page.fn1();
sinon.assert.calledOnce(stub);
});
这样在解决sinon.assert.calledOnce(stub);
后将被调用Page.fn1()
。
推荐阅读
- nuxt.js - 使用 Nuxt 和 Vuex 自动完成搜索?
- javascript - Nodejs异步函数未按顺序运行
- sql - 我想用 sqlmock 在单元测试中添加行,如何使用 sqlmock
- python - 用于 API 函数的 pytest monkeyPatch
- swift - 如何从 iOS 的系统词典中获取词义
- wcf - IIS 连接到 SoapUi 时握手失败 (40)
- reactjs - React Error - 在导出为模块之前将箭头函数分配给变量和
- python - Python/Pandas:数据框合并和填充
- python - CentOS7 的 Docker 映像中的 PIP python setup.py egg_info
- python - ValueError:传递值的形状为 (6, 6),在 pandas 中合并两个 df 时,索引暗示 (4, 6) 错误