如何在PollyJS与Jest同个测试文件中运行两个用例并解决第二个报错
问题根因
- 适配器配置不匹配:你当前使用的
@pollyjs/adapter-node-http仅支持拦截Node.js原生http/https模块发起的请求,无法覆盖Jest jsdom环境下的fetch请求,多测试用例运行时请求上下文混乱导致Polly无法匹配录制条目,返回空响应触发status读取报错。 - Jest Spy未清理:第一个测试用例中对
global.fetch做了jest.spyOn监听,但用例结束后没有调用mockRestore还原,第二个用例运行时fetch仍处于被mock劫持的状态,Polly无法正常接管请求。 - 测试隔离配置缺失:默认Polly配置未开启用例级的请求缓存隔离,多个用例共享同一实例的缓存数据,后续用例的请求无法正确匹配录制内容。
解决方案
步骤1:安装fetch适配器
执行命令安装@pollyjs/adapter-fetch用于拦截fetch请求:
npm install @pollyjs/adapter-fetch --save-dev
步骤2:修改Polly默认配置
更新setupDefaultPolly的配置,新增fetch适配器、开启用例隔离、完善请求匹配规则:
import FetchAdapter from '@pollyjs/adapter-fetch'; export const setupDefaultPolly = () => { const context = setupPolly({ mode: process.env.POLLY_MODE, // 新增fetch适配器,保留原有node-http适配器按需使用 adapters: [FetchAdapter, require('@pollyjs/adapter-node-http')], persister: require('@pollyjs/persister-fs'), // 开启测试用例隔离,每个用例独立匹配录制内容 isolateTests: true, recordIfMissing: true, persisterOptions: { fs: { recordingsDir: path.resolve(__dirname, '../__recordings__'), }, }, // 可选:调整请求匹配规则,避免参数/顺序导致匹配失败 matchRequestsBy: { method: true, url: { protocol: true, hostname: true, port: true, pathname: true, query: true }, body: true } }) return context }
步骤3:清理Jest Spy
在第一个测试用例结束后还原fetch的spy,或者直接移除不需要的spy(Polly本身可以统计请求次数):
it('should render correctly', async () => { const fetchSpy = jest.spyOn(global, 'fetch') let wrapper await act(async () => { wrapper = mount(<MyComponent thing="exists" />) }) expectLoadingPage(wrapper).toBeTruthy() await waitFor(() => { wrapper.update() expectLoadingPage(wrapper).toBeFalsy() }) expect(wrapper.text()).toContain('exists') expect(withoutMuiID(wrapper)).toMatchSnapshot() expect(fetchSpy).toHaveBeenCalledTimes(3) // 新增:还原spy,避免影响后续用例 fetchSpy.mockRestore() })
步骤4:重新生成录制文件
将环境变量POLLY_MODE设置为record,完整运行一次测试文件,生成包含两个用例请求的完整录制文件,之后切换为replay模式即可正常运行所有用例。
内容的提问来源于stack exchange,提问作者stbenjam
相关产品推荐
相关产品推荐

