如何用MSW拦截Firebase API请求?React测试报错排查
React + MSW 拦截Firebase请求失败问题排查与解决
报错核心原因
- MSW拦截规则不匹配带查询参数的URL
你的MSW Handler监听的是不带查询参数的https://travelsi-default-rtdb.firebaseio.com/posts.json,但实际请求带有?auth=USER-ACCESS-TOKEN参数,MSW默认精确匹配会跳过这类请求,导致拦截失败,触发真实网络请求报错。 - 测试用Redux Store未初始化accessToken
报错信息显示请求URL的auth参数为空,说明测试时Redux的state.auth.userData.accessToken未赋值,生成了不合法的请求URL,进一步导致真实请求失败。 - MSW响应数据存在语法错误
handlers.js的响应JSON中,id: p2是未定义变量(需改为字符串"p2"),且存在重复键名p1,这些语法错误会导致拦截成功后无法返回有效响应。
修复步骤
1. 修改MSW Handler,适配带查询参数的请求
MSW默认忽略URL查询参数进行匹配,只需修正响应数据的语法错误即可:
// handlers.js import { rest } from 'msw'; export const handlers = [ rest.get('https://travelsi-default-rtdb.firebaseio.com/posts.json', (req, res, ctx) => { // 可选:通过req.url.searchParams.get('auth')验证令牌 return res( ctx.status(200), ctx.json({ p1: { city: 'city 1', country: 'country', date: '01.01.2020', description: 'description', feelings: { f1: { reaction: 1, }, }, id: "p1", img: 'img', tag: '#tag', title: 'title 1', }, p2: { city: 'city 2', country: 'country', date: '01.01.2020', description: 'description', feelings: { f1: { reaction: 1, }, }, id: "p2", img: 'img', tag: '#tag', title: 'title 2', }, }) ); }), ];
2. 初始化测试用Redux Store的用户数据
测试时给Store注入带有效accessToken的初始状态,避免生成空参数的请求:
// AllPosts.test.js import { screen, render, waitFor } from '@testing-library/react'; import AllPosts from './AllPosts'; import { Provider } from 'react-redux'; import { createStore } from '../../../../store/index'; describe('AllPosts component', () => { test('posts are rendered correctly', async () => { // 创建带初始登录状态的Store const store = createStore({ auth: { userData: { accessToken: 'test-auth-token' } }, posts: { postsToRender: [] }, ui: {} }); render( <Provider store={store}> <AllPosts /> </Provider> ); // 使用RTL官方推荐的waitFor替代自定义延迟函数 await waitFor(() => { expect(screen.getByText('city 1')).toBeInTheDocument(); }); screen.debug(); }); });
3. 可选:给fetchPosts添加空值防护
避免accessToken为空时发起无效请求:
// fetchPosts.js export const fetchPosts = accessToken => { return async dispatch => { if (!accessToken) { dispatch( uiActions.setNotification({ status: 'error', type: 'get', message: '未获取到用户授权令牌', }) ); return; } // 原有的fetch逻辑... }; };
4. 验证拦截效果
在MSW Handler中添加日志,确认请求是否被成功拦截:
rest.get('https://travelsi-default-rtdb.firebaseio.com/posts.json', (req, res, ctx) => { console.log('MSW已拦截请求:', req.url); return res(/* ... */); })
内容的提问来源于stack exchange,提问作者Maciej
相关产品推荐
相关产品推荐

