使用Jest测试RTK Query时token放查询参数认证失败如何解决?
问题根因
你的核心问题出在token的获取时机:
- 你在
dataEndpoint.ts模块顶层调用getToken(),模块加载时就会执行这行代码拿到固定的token值,而测试环境下模块加载时localStorage里还没有设置有效token,最终发起请求时token参数为空/无效,触发401。 - 另外你的测试代码里存在几处拼写错误也会导致执行异常:
cosnt应为const、waitForNextupdate应为waitForNextUpdate、JSON.string应为JSON.stringify。
修复步骤
- 调整端点定义逻辑,将token获取移到query函数内部,每次请求发起时动态读取,避免模块加载时固定死token值
- 测试前置操作中往localStorage写入有效测试token
- 可选:配置fetchMock校验请求token参数,符合预期才返回成功响应
修改后的代码示例
端点代码(dataEndpoint.ts)
// 删掉模块级的token声明,移到query内部动态获取 export const apiWithData = rootApi.injectEndpoints({ endpoints: (build) => ({ fetchDataMetaList: build.mutation<DataType, any>({ query: ({offset = 0, size = 20, body}) => { const token = getToken(); // 每次发起请求时动态读token return { url: `${API_URL}?offset=${offset}&size=${size}&token=${token}`, method: "POST", body: body || {} } } }) }) })
测试代码(data.test.tsx)
const body = { offset: 0, size: 20, body: {} }; const updateTimeout = 10000; const TEST_TOKEN = 'test_valid_token_123'; // 测试用有效token // 替换为你getToken方法里读取的localStorage key const TOKEN_STORAGE_KEY = 'user_token'; beforeEach((): void => { fetchMock.resetMocks(); // 测试前置写入有效token到localStorage localStorage.setItem(TOKEN_STORAGE_KEY, TEST_TOKEN); }) const wrapper: React.FC = ({ children }) => { const storeRef = setupApiStore(rootApi); return <Provider store={storeRef.store}>{children}</Provider> } describe("useFetchDataMetaListMutation", () => { it("Success", async () => { // 配置mock校验token参数 fetchMock.mockIf(new RegExp(`${API_URL}.*`), async (req) => { const reqUrl = new URL(req.url); if (reqUrl.searchParams.get('token') === TEST_TOKEN) { // token匹配返回成功响应 return { status: 200, body: JSON.stringify(response) // 替换为你的mock返回值 } } // token不匹配返回401 return { status: 401, body: JSON.stringify({msg: 'Unauthorized'}) } }) const { result, waitForNextUpdate } = renderHook( () => useFetchDataMetaListMutation(), { wrapper } ) const [fetchDataMetaList, initialResponse] = result.current; expect(initialResponse.data).toBeUndefined(); expect(initialResponse.isLoading).toBe(false); act(() => { void fetchDataMetaList(body); }) const loadingResponse = result.current[1]; expect(loadingResponse.data).toBeUndefined(); expect(loadingResponse.isLoading).toBe(true); await waitForNextUpdate({ timeout: updateTimeout }); const loadedResponse = result.current[1]; expect(loadedResponse.isSuccess).toBe(true); expect(loadedResponse.data).toBeDefined(); }) })
内容的提问来源于stack exchange,提问作者user14459580
相关产品推荐
相关产品推荐

