Jest异步断言及函数调用校验异常,测试意外通过问题求助
问题根源
你遇到的断言全部误通过的核心原因是Jest默认按同步逻辑执行测试用例,你的异步请求、then回调里的逻辑还没执行完成,测试用例就已经标记为执行结束了,未执行的断言自然不会触发错误。同时你现有代码还存在两个逻辑错误:
- 断言位置错误:你把
expect写在了new Promise的同步执行块里,resolve(response)触发的then回调属于微任务,要等当前同步块执行完才会运行,此时setOptions还没被调用,就算测试等待异步完成,这两条断言的执行时机也是错的。 - 函数调用名不匹配:业务代码导出的函数是
callapi,测试代码里调用的是callGoogleAutoCompleteSearch,需要先修正。
修复方案
Jest支持多种处理异步测试的方式,这里推荐最常用的async/await方案,修改后的测试代码如下:
import axios from 'axios'; // 替换为你实际的业务代码文件路径,引入callapi函数 import { callapi } from './xxx'; describe('callapi tests', () => { it('should call setOptions with options when callapi is called', async () => { const response = { data: { status: 'OK', suggestions: [{"id":1},{"id":2}] } } const setOptions = jest.fn(); const expectedOptionsList = [ { key: 1 }, { key: 2 } ]; // mock axios.post直接返回已resolve的响应 axios.post = jest.fn(() => Promise.resolve(response)); const setSuggestStatus = jest.fn(); // 调用业务函数 callapi('input', setOptions, setSuggestStatus); // 等待所有微任务执行完成,确保then回调已经跑完 await Promise.resolve(); // 此处执行断言 expect(setOptions).toHaveBeenCalledWith(expectedOptionsList); expect(1).toBe(2); // 此时会正常抛出错误 expect(axios.post).toHaveBeenCalledTimes(1); // 可选,校验接口调用符合预期 }); });
可选替代方案
如果你更习惯用done回调通知Jest测试结束,也可以按如下写法实现:
it('should call setOptions with options when callapi is called', (done) => { const response = { data: { status: 'OK', suggestions: [{"id":1},{"id":2}] } } const setOptions = jest.fn(); const expectedOptionsList = [{ key: 1 }, { key: 2 }]; axios.post = jest.fn(() => Promise.resolve(response)) .mockImplementationOnce(() => { return Promise.resolve(response).then(() => { // 等业务逻辑的then执行完成后再断言 process.nextTick(() => { expect(setOptions).toHaveBeenCalledWith(expectedOptionsList); expect(1).toBe(2); done(); // 通知Jest测试执行完成 }) }) }); const setSuggestStatus = jest.fn(); callapi('input', setOptions, setSuggestStatus); });
内容的提问来源于stack exchange,提问作者bcourtney5965
相关产品推荐
相关产品推荐

