React 路由器 - useOutletContext 测试

Ar2*_*r26 7 reactjs react-router apollo-client react-testing-library

我正在使用react-router V6并尝试测试useOutletContext的新功能。我的测试库是testing-library/react,我不确定如何在测试中传递上下文数据。

在 TSX 组件中,我使用 React-router 的钩子获取数据:

const { data } = useOutletContext<IContext>()
Run Code Online (Sandbox Code Playgroud)

我需要类似的东西:

test("render outlet context data view", async () => {
  const { getByTestId } = render(
    <MockedProvider mocks={[mockData]} context={myContextData}>
       <ContextDataView />
    </MockedProvider>
)
Run Code Online (Sandbox Code Playgroud)

MockedProvider 标签来自@apollo/client/testing

context={myContextData} 部分是我需要的

Zan*_*der 11

我没有使用嘲笑,而是useOutletContext使用组合和 React RouterMemoryRouter来模仿真实应用程序的行为。

我创建了一个RenderRouteWithOutletContext应该用于包装您正在测试的组件的组件。

// RenderRouteWithOutletContext.tsx
import { ReactNode } from 'react';
import { MemoryRouter, Outlet, Route, Routes } from 'react-router-dom';

interface RenderRouteWithOutletContextProps<T = any> {
  context: T;
  children: ReactNode;
}

export const RenderRouteWithOutletContext = <T,>({
  context,
  children,
}: RenderRouteWithOutletContextProps<T>) => {
  return (
    <MemoryRouter>
      <Routes>
        <Route path="/"element={<Outlet context={context as T} />}>
          <Route index element={children} />
        </Route>
      </Routes>
    </MemoryRouter>
  );
};
Run Code Online (Sandbox Code Playgroud)

在你的测试文件中:

// YourComponent.test.tsx
import { screen, cleanup, render } from '@testing-library/react';
import { describe, expect, it, afterEach } from 'vitest';
import { RenderRouteWithOutletContext } from './RenderRouteWithOutletContext';

const mockOutletContextData: any = {
  foo: 'bar',
};

afterEach(() => {
  cleanup();
});

describe('PersonOverview', () => {
  it('should render as expected', () => {
    render(
      <RenderRouteWithOutletContext context={mockOutletContextData}>
        <YourComponent />
      </RenderRouteWithOutletContext>,
    );
    const component = screen.getByTestId('component-test-id');
    expect(component).toBeInTheDocument();
  });
});

Run Code Online (Sandbox Code Playgroud)

请注意,我上面使用的是 Vitest,但 Jest 版本几乎完全相同。

这个解决方案很棒,因为它与您的应用程序的实际使用方式非常相似。


小智 0

我在工作中也需要同样的东西,我的一位同事终于帮助我解决了这个问题。

在你的测试文件中

import * as rrd from 'react-router-dom';
Run Code Online (Sandbox Code Playgroud)

然后按照您的预期设置数据,并使用 Jest 来模拟 React-router-dom

let mockData = { mock: 'Data' }
jest.mock('react-router-dom');
Run Code Online (Sandbox Code Playgroud)

然后在你的测试中

test("render outlet context data view", async () => {
  rrd.useOutletContext.mockReturnValue(mockData)
  render(<ContextDataView />)
}
Run Code Online (Sandbox Code Playgroud)