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

使用Enzyme挂载组件时Relay的usePreloadedQuery触发渲染挂起如何解决

问题根因

  1. 你的测试代码中传入的查询变量和query定义的必填$someId参数不匹配,导致Relay的mock resolver没有命中对应查询,查询一直处于pending状态,触发usePreloadedQuery挂起。
  2. enzyme-adapter-react-16不支持Suspense组件,包裹后会触发unknown node with tag 2的内部报错,Enzyme本身已经停止维护,对React 16之后的并发特性兼容都有问题。

可行解决方案

方案1:Mock usePreloadedQuery (适合继续用Enzyme的场景)

直接mock react-relay的usePreloadedQuery hook,跳过真实的Relay查询逻辑,从根源上避免触发Suspense,也不用处理Relay mock环境的复杂配置:

jest.mock('react-relay', () => ({
  ...jest.requireActual('react-relay'),
  usePreloadedQuery: jest.fn(),
}));

it('should render correctly', () => {
  // 构造符合组件需要的mock数据,包含childComponentFragment所需字段
  const mockData = {
    something: {
      // 自定义模拟数据
    }
  };
  (usePreloadedQuery as jest.Mock).mockReturnValue({ data: mockData });

  const wrapper = mount(
    <ParentComponent queryReference={{} as any} />
  );
  expect(wrapper.find(ChildComponent)).toExist();
});

方案2:替换Enzyme为React Testing Library(推荐,符合Relay测试最佳实践)

React Testing Library对React新特性兼容更好,可以正常使用Suspense配合Relay官方测试工具,调整后的测试代码如下:

import { render, screen } from '@testing-library/react';
import { Suspense, act } from 'react';
import { RelayEnvironmentProvider, loadQuery } from 'react-relay';
import { createMockEnvironment, MockPayloadGenerator } from 'relay-test-utils';

it('should render correctly', async () => {
  const environment = createMockEnvironment();
  // 和query定义的变量完全匹配,不要传空对象
  const mockVariables = { someId: 'test-id' };
  
  environment.mock.queueOperationResolver((operation) =>
    MockPayloadGenerator.generate(operation, {
      Something: () => ({
        // 自定义模拟数据
      }),
    }),
  );
  environment.mock.queuePendingOperation(parentComponentQuery, mockVariables);

  let queryReference;
  act(() => {
    queryReference = loadQuery(environment, parentComponentQuery, mockVariables);
  });

  render(
    <RelayEnvironmentProvider environment={environment}>
      <Suspense fallback={<div>Loading...</div>}>
        <ParentComponent queryReference={queryReference} />
      </Suspense>
    </RelayEnvironmentProvider>
  );

  // 断言渲染内容符合预期
  expect(await screen.findByText('预期渲染的文本')).toBeInTheDocument();
});

内容的提问来源于stack exchange,提问作者T J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:54:08