【发布时间】:2021-03-16 21:27:25
【问题描述】:
我的商店的processAction() 函数以即发即弃的方式调用私有异步函数,然后执行获取。 processAction() 本身不处理任何错误处理,并且——在浏览器中——如果获取失败,外部库会处理所有未捕获的 Promise 拒绝。
因此,如果我模拟我的 fetch 以拒绝,私有函数(我正在测试的效果)将拒绝。由于我没有对异步函数调用创建的 Promise 的引用,因此我无法在测试中捕获拒绝,但测试失败,因为存在未处理的拒绝。
我如何让 jest 接受这个不调用私有函数本身而不是仅仅触发调用它的操作?
actions.ts
const actions = {
doTheThing() {
dispatch({ type: 'DO_THE_THING' });
},
};
export default actions;
store.ts
import fetch from './fetch';
class Store {
isFetching = false;
// ...
processAction({ type, payload }: { type: string, payload: any }) {
switch (type) {
case 'DO_THE_THING':
this.fetchTheThing();
break;
}
}
private async fetchTheThing() {
try {
this.isFetching = true;
const result = await fetch(myUrl);
// ...
} finally {
this.isFetching = false;
}
}
}
export default new Store();
__mocks__/fetch.ts
let val: any;
interface fetch {
__setVal(value: any): void;
}
export default async function fetch() {
return val;
}
fetch.__setVal = function(value: any) {
val = value;
};
store.test.ts
import actions from './actions';
import store from './store';
const fetch = (require('./fetch') as import('./__mocks__/fetch')).default;
jest.mock('./fetch');
test('it sets/unsets isFetching on failure', async () => {
let rej: () => void;
fetch.__setVal(new Promise((_, reject) => rej = reject));
expect(store.isFetching).toBe(false);
Actions.doTheThing();
await Promise.sleep(); // helper function
expect(store.isFetching).toBe(true);
rej(); // <---- test fails here
await Promise.sleep();
expect(store.isFetching).toBe(false);
});
【问题讨论】:
-
模拟捕获异常的超级骗子全局异常处理 API - 然后像在应用程序中那样使用该模拟。这才是正确的方法。以不复制已部署环境的方式测试您的代码是浪费时间并且不会进行有效的测试。
-
这个项目被加载到我无法控制的外壳中。 shell是处理super-duper异常处理的那个。
-
然后模拟shell
-
try { reject(); } catch(err) { //swallow } finally { await Promise.sleep(); expect(...); -
永远不应该发生“被拒绝的即发即弃的承诺”之类的事情。在编写测试时发现它是好的。所以修复它。
标签: javascript node.js typescript promise jestjs