在Jest中添加RTK Query中间件导致测试挂起问题
解决RTK Query组件测试挂起问题
问题原因
你在测试中同时执行了两个冲突操作:一是用jest.spyOn直接mock RTK Query生成的useGetDataByIdQuery hook,二是在测试store中添加了RTK Query的中间件。RTK Query的hook本身会与store中间件进行异步交互,但你的mock未处理这种交互逻辑,导致测试陷入无限等待;而移除中间件时,RTK Query的内部逻辑又会因依赖缺失报错。
解决方案
方案1:使用MSW Mock API请求(推荐)
用Mock Service Worker(MSW)拦截真实API请求,替代直接mock hook的方式,该做法更贴近真实业务场景,也能避免与RTK Query的store配置冲突。
- 安装MSW:
npm install msw --save-dev
- 创建Mock服务器:
// src/mocks/server.js import { setupServer } from 'msw/node' import { rest } from 'msw' // 替换为你实际的baseUrl和endpoint const baseUrl = '你的基础地址'; const endpoint = '你的接口路径'; export const server = setupServer( rest.get(`${baseUrl}/${endpoint}/123`, (req, res, ctx) => { return res(ctx.json({})) // 返回你需要的mock数据 }) )
- 修改测试文件:
/* 导入必要依赖 */ import { render, waitFor } from '@testing-library/react'; import { Provider } from 'react-redux'; import { configureStore } from '@reduxjs/toolkit'; import { dataApi } from './dataApi'; import Component from './component'; import { server } from './mocks/server'; let mockdata = { id: '123' }; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => mockdata, useRouteMatch: () => ({ url: '/data/123' }), })); // 测试前后启动/关闭Mock服务器 beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); // 正常配置包含RTK Query的store const store = configureStore({ reducer: { [dataApi.reducerPath]: dataApi.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(dataApi.middleware), }); test('should render wrapper correctly', async () => { const { container } = render( <Provider store={store}><Component/></Provider> ); // 用waitFor等待异步请求完成后再断言 await waitFor(() => { expect(container).toMatchSnapshot(); }); });
方案2:调整Mock逻辑与Store配置
如果坚持直接mock hook,需确保组件不再依赖store中的RTK Query配置,避免冲突:
修改测试文件中的store配置,移除RTK Query的reducer和中间件:
const store = configureStore({ reducer: { // 不需要添加dataApi的reducer }, // 不需要添加dataApi的中间件 }); // 或者使用Redux Toolkit的mockStore // import { createMockStore } from '@reduxjs/toolkit/testing'; // const store = createMockStore({});
此时你的hook mock会完全接管组件的数据逻辑,不会再与store的RTK Query中间件交互,测试就不会挂起,也不会出现缺少中间件的报错。
注意事项
- 禁止同时mock RTK Query hook和配置RTK Query的store中间件,二者会触发异步逻辑冲突
- 优先使用MSW模拟API请求,这是RTK Query官方推荐的测试方式
- 若使用mock hook的方式,必须确保组件不再依赖store中的RTK Query相关配置
内容的提问来源于stack exchange,提问作者Abbas Dahodwala
相关产品推荐
相关产品推荐

