如何为ApolloClient的缓存更新逻辑编写单元测试?
测试useMutation中update方法的缓存更新逻辑
依赖准备
确保测试环境已安装以下依赖:
@apollo/client/testing:提供MockedProvider和缓存操作工具@testing-library/react:用于渲染Hook、触发异步操作@testing-library/jest-dom:用于断言缓存数据
完整测试代码示例
import { renderHook, act } from '@testing-library/react'; import { MockedProvider, InMemoryCache } from '@apollo/client/testing'; import { useMutation } from '@apollo/client'; import updateRecordMutation from './path-to-your-mutation-file'; import GetRecord from './path-to-your-get-record-query'; // 测试用初始缓存数据 const initialCacheData = { Record: { __typename: 'Record', recordId: '123', recordName: '旧名称' } }; // Mutation的模拟返回结果 const mockMutationResult = { data: { updateRecord: { __typename: 'UpdateRecordResponse', recordName: '新名称' } } }; describe('useMutation的update缓存更新逻辑', () => { it('能正确更新缓存中的recordName字段', async () => { // 初始化缓存并写入初始数据 const cache = new InMemoryCache(); cache.writeQuery({ query: GetRecord, variables: { recordId: '123' }, data: initialCacheData }); // 渲染Hook并包裹MockedProvider const { result } = renderHook(() => useMutation(updateRecordMutation), { wrapper: ({ children }) => ( <MockedProvider mocks={[ { request: { query: updateRecordMutation, variables: { recordId: '123', recordName: '新名称' } }, result: mockMutationResult } ]} cache={cache} > {children} </MockedProvider> ) }); const [updateRecord] = result.current; // 触发Mutation调用(用act包裹确保状态更新完成) await act(async () => { await updateRecord({ variables: { recordId: '123', recordName: '新名称' }, // 直接复用组件中的update逻辑,避免重复编写 update(cache, result) { const updatedData = result.data?.updateRecord?.recordName; const cachedData = cache.readQuery({ query: GetRecord, variables: { recordId: '123' }, }); if (cachedData?.Record) { cachedData.Record.recordName = updatedData; cache.writeQuery({ query: GetRecord, variables: { recordId: '123' }, data: cachedData, }); } } }); }); // 读取缓存并验证更新结果 const updatedCacheData = cache.readQuery({ query: GetRecord, variables: { recordId: '123' } }); expect(updatedCacheData?.Record.recordName).toBe('新名称'); }); });
关键注意事项
- 必须预加载初始缓存:如果不提前写入初始数据,update方法中
cache.readQuery会返回undefined,直接跳过更新逻辑。 - 严格匹配请求参数:MockedProvider中配置的request的variables,必须和调用updateRecord时的variables完全一致,否则Mutation不会触发模拟返回,update方法也不会执行。
- 用act包裹异步操作:确保Mutation和缓存更新的异步逻辑全部完成后再做断言,避免测试不稳定。
- 复用业务逻辑:把组件中的update逻辑抽成独立函数,测试时直接调用该函数,保证测试逻辑和业务逻辑完全一致,减少维护成本。
缓存未更新的常见排查点
- 初始缓存未正确写入,导致
cachedData为undefined - Mutation的模拟返回结构和实际不一致,比如缺少
updateRecord字段,导致updatedData为undefined - 请求参数和Mock配置不匹配,Mutation未触发模拟返回
- 写入缓存时的query、variables和读取时不一致,导致无法读取到更新后的数据
内容的提问来源于stack exchange,提问作者athi
相关产品推荐
相关产品推荐

