React Query乐观更新测试问题求助:用例失效及mock方法咨询
React Query 乐观更新测试失败排查及方法Mock咨询
我正在为React Query中的乐观更新编写测试用例,但测试无法正常运行。仅保留onSuccess逻辑时功能正常,添加乐观更新相关逻辑后就失效了。附上我的测试代码和自定义Hook代码,希望能得到帮助,同时想咨询如何在测试中mock getQueryData和setQueryData方法。
测试代码
import { act, renderHook } from "@testing-library/react-hooks"; import axios from "axios"; import { createWrapper } from "../../test-utils"; import { useAddColorHook, useFetchColorHook } from "./usePaginationReactQuery"; jest.mock("axios"); describe('Testing custom hooks of react query', () => { it('Should add a new color', async () => { axios.post.mockReturnValue({data: [{label: 'Grey', id: 23}]}) const { result, waitFor } = renderHook(() => useAddColorHook(1), { wrapper: createWrapper() }); await act(() => { result.current.mutate({ label: 'Grey' }) }) await waitFor(() => result.current.isSuccess); }) }) export const createTestQueryClient = () => new QueryClient({ defaultOptions: { queries: { retry: false, cacheTime: Infinity, }, }, logger: { log: console.log, warn: console.warn, error: () => {}, } }); export function createWrapper() { const testQueryClient = createTestQueryClient(); return ({ children }) => ( <QueryClientProvider client={testQueryClient}> {children} </QueryClientProvider> ); }
自定义Hook代码
export const useAddColorHook = (page) => { const queryClient = useQueryClient() return useMutation(addColor, { // onSuccess: () => { // queryClient.invalidateQueries(['colors', page]) // } onMutate: async color => { // newHero refers to the argument being passed to the mutate function await queryClient.cancelQueries(['colors', page]) const previousHeroData = queryClient.getQueryData(['colors', page]) queryClient.setQueryData(['colors', page], (oldQueryData) => { return { ...oldQueryData, data: [...oldQueryData.data, { id: oldQueryData?.data?.length + 1, ...color }] } }) return { previousHeroData } }, onSuccess: (response, variables, context) => { queryClient.setQueryData(['colors', page], (oldQueryData) => { console.log(oldQueryData, 'oldQueryData', response, 'response', variables, 'var', context, 'context', 7984) return { ...oldQueryData, data: oldQueryData.data.map(data => data.label === variables.label ? response.data : data) } }) }, onError: (_err, _newTodo, context) => { queryClient.setQueryData(['colors', page], context.previousHeroData) }, onSettled: () => { queryClient.invalidateQueries(['colors', page]) } }) }
问题排查与解决
1. 测试失败的核心原因
测试中未预先为['colors', 1]查询键设置初始缓存数据,导致onMutate阶段调用getQueryData返回undefined,后续执行oldQueryData.data时触发报错,直接导致测试流程中断。仅保留onSuccess时,逻辑不依赖缓存初始数据,因此不会触发该错误。
2. 修复测试的具体步骤
步骤1:修改测试代码,预先设置缓存初始数据
it('Should add a new color', async () => { // 注意:axios.post需用mockResolvedValue,因为原方法返回Promise axios.post.mockResolvedValue({data: [{label: 'Grey', id: 23}]}) // 创建测试用QueryClient并设置初始缓存 const testQueryClient = createTestQueryClient(); testQueryClient.setQueryData(['colors', 1], { data: [{label: 'Red', id: 1}] // 模拟已有数据 }); // 将预设置好的QueryClient传入wrapper const { result, waitFor } = renderHook(() => useAddColorHook(1), { wrapper: createWrapper(testQueryClient) }); await act(async () => { result.current.mutate({ label: 'Grey' }) }) await waitFor(() => result.current.isSuccess); // 验证缓存数据是否正确更新 const updatedData = testQueryClient.getQueryData(['colors', 1]); expect(updatedData.data).toContainEqual({label: 'Grey', id: 23}); })
步骤2:修改createWrapper,支持传入自定义QueryClient
export function createWrapper(testQueryClient) { // 优先使用传入的client,否则创建新实例 const client = testQueryClient ?? createTestQueryClient(); return ({ children }) => ( <QueryClientProvider client={client}> {children} </QueryClientProvider> ); }
3. Mock getQueryData和setQueryData的方法
若需单独mock这两个方法,可通过jest spyOn监听测试用QueryClient实例:
const testQueryClient = createTestQueryClient(); // Mock getQueryData const mockGetQueryData = jest.spyOn(testQueryClient, 'getQueryData') .mockReturnValue({data: [{label: 'Blue', id: 2}]}); // Mock setQueryData const mockSetQueryData = jest.spyOn(testQueryClient, 'setQueryData') .mockReturnValue(); // 测试后清理mock afterEach(() => { jest.clearAllMocks(); });
内容的提问来源于stack exchange,提问作者Rohit Kumar
相关产品推荐
相关产品推荐

