使用Enzyme挂载组件时Relay的usePreloadedQuery触发渲染挂起如何解决
问题根因
- 你的测试代码中传入的查询变量和query定义的必填
$someId参数不匹配,导致Relay的mock resolver没有命中对应查询,查询一直处于pending状态,触发usePreloadedQuery挂起。 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
相关产品推荐
相关产品推荐

