You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Apollo Client与React Testing Library测试含subscribeToMore的自定义Hook时遭遇变量匹配错误

Apollo Client与React Testing Library测试含subscribeToMore的自定义Hook时遭遇变量匹配错误

看起来你在测试使用Apollo Client subscribeToMore的自定义Hook时,遇到了查询变量与Mock不匹配的问题,这是测试Apollo Client时很常见的坑,咱们一步步来排查修复:

核心问题分析

从错误信息能看出来,你的实际请求变量和Mock里定义的变量完全对不上,主要有这几个原因:

  1. 拼写低级错误:实际请求里是offset:0,但Mock里写成了offest:0(少了一个s);订阅Mock里的fleedId也是拼写错误,应该是fleetId。
  2. Mock变量与实际请求不匹配:测试调用useFetchShipEvents({ limit: 10, fleetId: 1 })时,没传shipId、cameraId、companyId、withHidden,所以这些变量实际是undefined,但你Mock里给的都是具体值(比如shipId:1)。
  3. 冗余变量与字段不匹配: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,提问作者אור ברמן

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 10:19:29