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

使用React Testing Library的Mocked Apollo Provider未返回数据问题

Apollo Client + React Testing Library 测试问题排查与解决

问题场景

基于Apollo Client的React组件中,使用useComponentRespQuery时配置了variables和skip参数,用React Testing Library结合MockedProvider测试时,mock数据无法正常返回;只有注释掉这些配置参数,Apollo才能返回正确的mock值。

组件核心代码:

const ComponentToTest = () => {
  // ...
  const { data, loading } = useComponentRespQuery({
    variables: {
      id: idValue
    },
    skip: !idValue
  });

  if (loading) {
    return <>Loading</>;
  }
  // ...
}

测试核心代码:

const componentRender = (mockGraphQLData: any, initialEntry: string = "") => render(
  <MemoryRouter initialEntries={[initialEntry]}>
    <MockedProvider mocks={[ mockGraphQLData ]} addTypename={false}>
      <ComponentToTest />
    </MockedProvider>
  </MemoryRouter>
);

describe("ComponentToTest", () => {
  it("should render a component to test", async() => {
    componentRender(zoneMock);
    const placeHolderValues = await screen.findByText(/Bla/i);
    expect(placeHolderValues).toBeInTheDocument();
  });
  // ...
}

GraphQL Query定义:

query GetResp($id: ID!) {
  resp(id: $id) {
    id
    name
    description
    controls {
      id
      name
    }
  }
}

现有Mock数据:

export const componentRespMock = {
  request: {
    query: componentRespDocument
  },
  result: {
    data: {
      resp: {
        id: "ID",
        name: "NAME",
        description: "DESCRIPTION",
        controls: [
          {
            id: "CTRL_2",
            name: "Second control"
          }
        ]
      }
    }
  }
};

解决方案

1. 确保Mock请求与组件请求的参数完全匹配

Apollo的MockedProvider会严格匹配Query和Variables,如果Mock的request没有包含variables,而组件请求时带了variables,则无法匹配到Mock数据,导致请求无响应。

修改Mock数据,添加与组件请求一致的variables:

export const componentRespMock = {
  request: {
    query: componentRespDocument,
    variables: { id: "ID" } // 需与组件中idValue的测试值完全一致
  },
  result: {
    data: {
      resp: {
        id: "ID",
        name: "NAME",
        description: "DESCRIPTION",
        controls: [
          {
            id: "CTRL_2",
            name: "Second control"
          }
        ]
      }
    }
  }
};

2. 保证测试时skip条件为false

组件中skip: !idValue,如果测试时idValue为空,Query会被跳过,MockedProvider不会收到请求,自然无法返回Mock数据。

确保测试时组件能获取到有效的idValue,比如通过路由传递:

it("should render a component to test", async() => {
  // 传入包含id的路由路径,确保组件能获取到idValue为"ID"
  componentRender(componentRespMock, "/your-component-path/ID");
  const placeHolderValues = await screen.findByText(/NAME/i);
  expect(placeHolderValues).toBeInTheDocument();
});

3. 验证异步流程的完整性

虽然findByText是异步查询,但可以额外等待Loading状态结束,确保Query请求已完成:

it("should render a component to test", async() => {
  componentRender(componentRespMock, "/your-component-path/ID");
  // 等待Loading消失,确认Query请求完成
  await waitFor(() => expect(screen.queryByText("Loading")).not.toBeInTheDocument());
  const placeHolderValues = await screen.findByText(/NAME/i);
  expect(placeHolderValues).toBeInTheDocument();
});

4. 排查是否存在未Mock的其他Query

如果组件中还有其他未被Mock的GraphQL Query,MockedProvider会抛出错误,导致组件无法正常渲染。可以在测试中添加错误检查:

it("should render a component to test", async() => {
  componentRender(componentRespMock, "/your-component-path/ID");
  // 确保没有GraphQL错误提示
  expect(await screen.queryByText(/Error/i)).not.toBeInTheDocument();
  const placeHolderValues = await screen.findByText(/NAME/i);
  expect(placeHolderValues).toBeInTheDocument();
});

内容的提问来源于stack exchange,提问作者Jean-Baptiste

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:05:51