为何Jest测试预期与实际值不符却显示通过?附相关代码与报错
问题排查:Jest测试预期失败却通过 + UnhandledPromiseRejectionWarning警告
我来帮你拆解这两个问题的根源和修复方案:
一、Jest测试预期不匹配却显示通过的原因
你的测试代码里,try-catch的错误处理逻辑完全绕过了Jest的失败检测机制,导致断言失败时Jest根本不知道测试出问题了。先看你的核心代码:
it('User is already present as a supplier', (done) => { const store = mockStore({}, [{ type: 'get_user', data: { } }]); return store.dispatch(userGetAction({ role: 'supplier' }, () => {})) .then(() => { try { expect(store.getActions()[0].data.disabled).toEqual(true); expect(store.getActions()[0].data.errormessage).toEqual('User is already present as a assitantbuyer'); } catch (err) { console.log(err); // 只打印错误,没告诉Jest测试失败 } done(); // 不管有没有错误,都标记测试完成 }) .catch(() => { done(); // 同样,catch里直接结束测试,没传递错误 }); });
具体问题:
- 断言错误被吞掉:当
expect不匹配时会抛出错误,但你在try-catch里只打印了错误,没有把这个错误传给done(err)——Jest只有收到done(err)才会标记测试失败,否则只要done()被调用,就默认测试通过。 - 预期值拼写错误:从控制台输出能看到,实际错误信息是
"User is already present as a assitant buyer"(多了空格),但你的预期值是"User is already present as a assitantbuyer",这也是断言不匹配的直接原因。
修复方案:
去掉多余的try-catch,让Jest自动捕获断言错误,同时正确使用done:
it('User is already present as a supplier', (done) => { const store = mockStore({}, [{ type: 'get_user', data: { } }]); store.dispatch(userGetAction({ role: 'supplier' }, () => {})) .then(() => { expect(store.getActions()[0].data.disabled).toEqual(true); // 修正拼写,和实际值匹配 expect(store.getActions()[0].data.errormessage).toEqual('User is already present as a assitant buyer'); done(); // 只有断言成功才结束测试 }) .catch(err => { done(err); // 把错误传给Jest,标记测试失败 }); });
更推荐用async/await简化代码(不需要手动管理done):
it('User is already present as a supplier', async () => { const store = mockStore({}, [{ type: 'get_user', data: { } }]); await store.dispatch(userGetAction({ role: 'supplier' }, () => {})); expect(store.getActions()[0].data.disabled).toEqual(true); expect(store.getActions()[0].data.errormessage).toEqual('User is already present as a assitant buyer'); });
二、UnhandledPromiseRejectionWarning警告的原因
你的Redux Thunk代码里,Promise链的错误处理有漏洞,导致部分rejection没有被正确捕获。看你的代码:
const buyerAction = (data = {}, cb) => dispatch => axios({ method: 'POST', url: `http://localhost:3001/api/manageUsers`, headers: { 'x-access-token': authService.getAccessToken() }, data }).then(res => new Promise((resolve, reject) => { if (res.status === 200 && res.data) { dispatch({ type: 'buyer_created', data: res.data.message }); if (data.role === 'buyer') { axios({ method: 'POST', url: `http://localhost:3001/api/populateBuyerLookUp`, headers: { 'x-access-token': authService.getAccessToken() }, data }) .then((response) => { resolve(response); }).catch((err) => { reject(err); }); } cb(res.data.message); // 这里会在populate请求完成前执行cb } else { reject(res); } })) .catch(() => { console.log('error'); // 只打印错误,没处理rejection });
具体问题:
- 外层catch吞掉了错误:当内层Promise(比如
populateBuyerLookUp请求失败)被reject时,外层的catch只打印了error,但没有重新抛出错误。如果调用buyerAction的地方没有额外的.catch(),Node.js就会抛出UnhandledPromiseRejectionWarning。 - cb调用时机错误:当
data.role === 'buyer'时,你在发起populateBuyerLookUp请求后立刻调用了cb,但这个请求是异步的,会导致cb在请求完成前执行,可能引发逻辑错误。 - 嵌套Promise增加了错误处理复杂度:嵌套的Promise链让错误传递路径不清晰,容易遗漏处理。
修复方案:
重构Promise链,改用链式then,并正确处理错误传递:
const buyerAction = (data = {}, cb) => dispatch => axios({ method: 'POST', url: `http://localhost:3001/api/manageUsers`, headers: { 'x-access-token': authService.getAccessToken() }, data }).then(res => { // 先判断请求是否成功,失败则抛出错误 if (!(res.status === 200 && res.data)) { throw new Error('Request failed or no data received'); } dispatch({ type: 'buyer_created', data: res.data.message }); // 如果是buyer角色,执行populate请求,否则直接返回当前res if (data.role === 'buyer') { return axios({ method: 'POST', url: `http://localhost:3001/api/populateBuyerLookUp`, headers: { 'x-access-token': authService.getAccessToken() }, data }); } return res; }).then(response => { // 确保cb在所有异步操作完成后执行 cb(response.data?.message || response.data); return response; }).catch(err => { console.error('Error in buyerAction:', err); // 重新抛出错误,让调用者可以捕获并处理 throw err; });
关键修复点:
- 去掉嵌套的Promise,改用链式
then,让错误可以沿着链自动传递。 - 在
catch里打印错误后重新抛出,这样调用buyerAction的地方可以通过.catch()处理错误,避免警告。 - 把
cb的调用放到最后一个then里,确保所有异步操作完成后再执行回调。
内容的提问来源于stack exchange,提问作者bikky barnwal
相关产品推荐
相关产品推荐

