使用Apollo Client与React Testing Library测试含subscribeToMore的自定义Hook时遭遇变量匹配错误
Apollo Client与React Testing Library测试含subscribeToMore的自定义Hook时遭遇变量匹配错误
看起来你在测试使用Apollo Client subscribeToMore的自定义Hook时,遇到了查询变量与Mock不匹配的问题,这是测试Apollo Client时很常见的坑,咱们一步步来排查修复:
核心问题分析
从错误信息能看出来,你的实际请求变量和Mock里定义的变量完全对不上,主要有这几个原因:
- 拼写低级错误:实际请求里是
offset:0,但Mock里写成了offest:0(少了一个s);订阅Mock里的fleedId也是拼写错误,应该是fleetId。 - Mock变量与实际请求不匹配:测试调用
useFetchShipEvents({ limit: 10, fleetId: 1 })时,没传shipId、cameraId、companyId、withHidden,所以这些变量实际是undefined,但你Mock里给的都是具体值(比如shipId:1)。 - 冗余变量与字段不匹配:Mock里重复定义了
withHidden(既在filter里又在顶层),而且订阅返回的字段名和Hook里的取值不一致(Hook里取shipEventAdded,Mock里写的是eventAdded)。
具体修复步骤
1. 先修正拼写错误
- 把
shipEventsMockQuery里的offest:0改成offset:0; - 把
shipEventsSubscriptionmock里的fleedId:1改成fleetId:1。
2. 让Mock变量完全匹配实际请求
根据测试传入的参数,调整Mock的变量,和实际请求的undefined值保持一致:
export const shipEventsMockQuery = [ { request: { query: GET_EVENTS, variables: { limit: 10, offset: 0, exclude: { eventType: ['LEAKAGE', 'WATCHMAN'] }, // 和Hook里noExclude默认false的逻辑一致 filter: { shipId: undefined, // 测试没传,所以是undefined cameraId: undefined, companyId: undefined, fleetId: 1, withHidden: undefined, }, }, }, // 保持原result数据不变 }, ];
3. 修正订阅Mock的字段与变量
确保订阅返回的字段名和Hook里的取值一致,同时变量匹配测试场景:
export const shipEventsSubscriptionmock = [ { request: { query: subscriptions.eventAdded, variables: { fleetId: 1, // 测试传入的fleetId shipId: undefined, // 测试没传shipId groupedShipIds: undefined, // 测试里没mock用户数据的话,这里就是undefined exclude: { eventType: ['LEAKAGE', 'WATCHMAN'] }, }, }, result: { data: { shipEventAdded: { // 修正为Hook里使用的字段名 burnedImage1Url: null, burnedImage2Url: null, burnedVodUrl: null, camera: { id: 1290, shipId: 1, shipCameraId: 4, location: null, description: null, title: '4', }, cameraId: 1290, endTime: null, eventState: 'NOT_ACKNOWLEDGED', eventType: 'PPE_HELMET', id: 58028, image1Url: null, image2Url: null, isCameraDisabled: false, lastPersonTime: null, liveUrl: null, notes: null, recordingStartTime: null, severity: 'INTERMEDIATE', shipEventId: 423421342, shipId: 1, speed: null, startTime: '2023-03-10T06:26:30.706Z', vodHlsUrl: null, vodPath: null, __typename: 'ShipEvent', }, }, }, }, ];
4. 补充用户数据的Mock(可选)
如果你的Hook依赖userStore里的groupedShipIds,需要在测试里mock这个数据:
jest.mock('../path/to/your/userStore', () => ({ userStore: { userAuth: { authUser: jest.fn().mockReturnValue({ attributes: { 'custom:grouped_Shipid': JSON.stringify([1,2]) } }), userAdmin: jest.fn().mockReturnValue(false) } } }));
5. 优化测试等待逻辑
调整测试里的等待逻辑,确保等待数据加载完成:
it('test1', async () => { const { result } = getHookWrapper(mocks); await act(async () => { result.current.fetchEvents(); // 等待加载状态结束,数据返回 await waitFor(() => expect(result.current.isEventsLoading).toBe(false), { timeout: 2000 }); }); expect(result.current?.shipEvents?.events?.length).toBe(1); });
备注:内容来源于stack exchange,提问作者אור ברמן
相关产品推荐
相关产品推荐

