Javascript 如何在promise.finally()中测试promise的状态,而无需在生产代码中等待它
我在生产代码中使用(或在Javascript 如何在promise.finally()中测试promise的状态,而无需在生产代码中等待它,javascript,promise,jestjs,try-catch-finally,Javascript,Promise,Jestjs,Try Catch Finally,我在生产代码中使用(或在async函数中尝试catch finally)执行一些后续代码,而不更改当前承诺的解决/拒绝状态 然而,在我的玩笑测试中,我想检测finally块中的承诺没有被拒绝 编辑:但我不想实际等待我的“生产”代码中的承诺(在那里,我只关心catch重新抛出的错误,而不关心finally中的错误) 我如何测试它?或者至少是如何模仿Promise.prototype来拒绝当前的承诺 例如,如果我要测试reduxaction创建者,即使有未处理承诺拒绝的消息,测试也会通过: tes
async
函数中尝试catch finally)执行一些后续代码,而不更改当前承诺的解决/拒绝状态
然而,在我的玩笑测试中,我想检测finally块中的承诺没有被拒绝
编辑:但我不想实际等待我的“生产”代码中的承诺(在那里,我只关心catch重新抛出的错误,而不关心finally中的错误)
我如何测试它?或者至少是如何模仿Promise.prototype来拒绝当前的承诺
例如,如果我要测试redux
action创建者,即使有未处理承诺拒绝的消息,测试也会通过:
test(“最终”,异步()=>{
const actions=await dispatchMock(add(“forgottenParent”,{a:1}));
const newState=actions.reduce(reducer,未定义);
expect(newState).toEqual({});
});
const dispatchMock=async thunk=>{…};
//----简化的“生产”代码-----
const reducer=(state={},action)=>state;
const add=parentId=>async dispatch=>{
调度(“添加启动”);
试一试{
等待someFetch(“someData”);
发送(“添加成功”);
}捕获(e){
发送(“添加失败”);
投掷e;
}最后{
dispatch(get(parentId));//如果此处的承诺被拒绝,则测试通过
}
};
const get=id=>async dispatch=>{
调度(“启动”);
试一试{
等待取数(id);
发送(“获得成功”);
}捕获(e){
调度(“获取失败”);
投掷e;
}
};
const someFetch=async id=>{
如果(id==“被遗忘的父母”){
抛出新错误(“想象我忘记模拟这个请求”);
}
承诺。解决(id);
};
在那一行没有例外get(parentId)
可能会返回一个被拒绝的承诺(或稍后将被拒绝的挂起承诺),但这不是一个例外,不会影响控制流
你可能在找
const add = parentId => async dispatch => {
dispatch("add start");
try {
await someFetch("someData");
dispatch("add success");
} catch (e) {
dispatch("add failed");
throw e;
} finally {
await dispatch(get(parentId));
// ^^^^^
}
};
请注意。编辑:更多通用解决方案可在
可以将承诺存储在某个仅用于测试的辅助函数中可访问的变量中,例如:
export const _getPromiseFromFinallyInTests = () => _promiseFromFinally
let _promiseFromFinally
const add = parentId => async dispatch => {
...
} finally {
// not awaited here because I don't want to change the current Promise
_promiseFromFinally = dispatch(get(parentId));
}
};
并将测试更新为仅等待测试承诺:
test("finally", async () => {
...
// but I want to fail the test if the Promise from finally is rejected
await _getPromiseFromFinallyInTests()
});
您是说在
get
内部还是dispatch
内部引发异常?如果在正常(同步)和async
/wait
中最终在内部引发异常(而不是在使用承诺方法链接时)应该在顶层await
重新抛出异常,除非它在两者之间的某个地方被吞没。如果您看到异常被默默地吞噬,我建议在JavaScript调试器中使用“在所有抛出的异常上中断”(或类似命名的选项)。默认情况下,大多数JS调试器仅因_未处理u/uncaught异常而中断。希望通过这种方式,您可以看到它在哪里被抓到和吞下。@Dai它被扔到get
的catch block bythrow e
中。不,不,它是按照规范工作的,从外部承诺的已解决状态来看,内部的异常被忽略=>它被最终
本身吞没了,这是正确的行为(但我想在我的测试中改变这种行为)-参见“测试”选项卡和“问题”子选项卡在链接的代码上执行Sandbox只是为了清楚起见,将在顶层重新引发异常。但它不会拒绝承诺,也不会使异步测试失败。等待被拒绝的承诺最终不会改变已解决的外部承诺。。。我知道这不是一个最佳实践,这就是为什么我想测试它不会发生=>如果它发生,我需要测试失败happens@Aprillion我无法复制<代码>异步函数示例({try{throw new Error(“internal”);}最终{wait Promise.reject(new Error(“outer”);}
肯定会以外部错误拒绝,并忽略内部错误。内部无throwtry
plz-异步函数示例({try{return 1}最终{wait Promise.reject(new Error(“outer”);}}}
@Aprillion不管try
块做什么-它总是从最后抛出外部错误,并拒绝示例()
,即使返回1嗯,也许Jest在做一些不规范的事情。。codesandbox中的测试目前对我不起作用-如果我设法更新我的示例,我会回来的
test("finally", async () => {
...
// but I want to fail the test if the Promise from finally is rejected
await _getPromiseFromFinallyInTests()
});