programing

얕은 테스트 효소 Reactjs를 사용하여 useLocation() 경로 이름을 어떻게 시뮬레이션합니까?

showcode 2023. 3. 6. 21:37
반응형

얕은 테스트 효소 Reactjs를 사용하여 useLocation() 경로 이름을 어떻게 시뮬레이션합니까?

다음과 같은 헤더 컴포넌트가 있습니다.

import { useLocation } from "react-router-dom";

const Header = () => {
   let route = useLocation().pathname; 
   return route === "/user" ? <ComponentA /> : <ComponentB />;
}

이 useLocation()을 어떻게 모의하여 사용자로 경로를 얻습니까?

오류가 발생하여 테스트 파일에서 Header 컴포넌트를 호출할 수 없습니다.

TypeError: useLocation에서 정의되지 않은 속성 'location'을 읽을 수 없습니다.

describe("<Header/>", () => {
    it("call the header component", () => {
        const wrapper = shallow(<Header />);
        expect(wrapper.find(ComponentA)).toHaveLength(1);
    });
});

"새로운 리액트라우터 후크를 사용하여 컴포넌트를 테스트하는 방법" 링크와 비슷하게 표시하려고 했지만 작동하지 않았습니다.

다음과 같이 시도했습니다.

const wrapper = shallow(
      <Provider store={store}>
        <MemoryRouter initialEntries={['/abc']}>
          <Switch>
            <AppRouter />
          </Switch>
        </MemoryRouter>
      </Provider>,
    );
    jestExpect(wrapper.find(AppRouter)
      .dive()
      .find(Route)
      .filter({path: '/abc'})
      .renderProp('render', { history: mockedHistory})
      .find(ContainerABC)
    ).toHaveLength(1);

테스트 리액트 라우터와 얕은 렌더링 링크에서 확인했지만 작동하지 않았습니다.

알려주세요.

잘 부탁드립니다.

다음 패턴을 사용하여 useLocation과 같은 리액트라우터 후크를 모사할 수 있습니다.

import React from "react"
import ExampleComponent from "./ExampleComponent"
import { shallow } from "enzyme"

jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  useLocation: () => ({
    pathname: "localhost:3000/example/path"
  })
}));

describe("<ExampleComponent />", () => {
  it("should render ExampleComponent", () => {
    shallow(<ExampleComponent/>);
  });
});

ExampleComponent에서 useLocation을 호출한 경우 위의 패턴을 통해 효소/제스트 테스트에서 컴포넌트를 오류 없이 얕은 렌더링할 수 있습니다.

나도 요즘 이것 때문에 힘들어...

이게 꽤 잘 작동한다는 걸 알았어요.

import React from "react"
import ExampleComponent from "./ExampleComponent"
import { shallow } from "enzyme"

const mockUseLocationValue = {
    pathname: "/testroute",
    search: '',
    hash: '',
    state: null
}
jest.mock('react-router', () => ({
    ...jest.requireActual("react-router") as {},
    useLocation: jest.fn().mockImplementation(() => {
        return mockUseLocationValue;
    })
}));

describe("<ExampleComponent />", () => {
  it("should render ExampleComponent", () => {
    mockUseLocationValue.pathname = "test specific path";
    shallow(<ExampleComponent/>);
    ...
    expect(...
  });
});

이를 통해 useLocation을 시뮬레이션하고 필요에 따라 특정 테스트에서 경로 이름 값을 제공할 수 있었습니다.

HTH

사용하시는 경우 react-testing-library:

import React from 'react';
import { Router } from 'react-router-dom';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import Component from '../Component.jsx';

test('<Component> renders without crashing', () => {
    const history = createMemoryHistory();

    render(
        <Router history={history}>
            <Component />
        </Router>
    );
});

상세정보 : https://testing-library.com/docs/example-react-router/

이것이 당신의 질문에 대한 직접적인 답변이 아니라는 것을 알지만, 만약 당신이 브라우저의 위치나 이력을 테스트하고 싶다면, 당신은 다음을 사용할 수 있습니다.mount추가 추가Route마지막으로 기록 및 위치 객체를 "수정"할 수 있습니다.

test(`Foobar`, () => {
  let testHistory
  let testLocation

  const wrapper = mount(
    <MemoryRouter initialEntries={[`/`]}>
      <MyRoutes />
      <Route
        path={`*`}
        render={routeProps => {
          testHistory = routeProps.history
          testLocation = routeProps.location
          return null
        }}/>
    </MemoryRouter>
  )

  // Manipulate wrapper

  expect(testHistory)...
  expect(testLocation)...
)}

시도해 보셨습니까?

describe("<Header/>", () => {
    it("call the header component", () => {
        const wrapper = shallow(<MemoryRouter initialEntries={['/abc']}><Header /></MemoryRouter>);
        expect(wrapper.find(Header).dive().find(ComponentA)).toHaveLength(1);
    });
});

얕은 곳을 사용하면 첫 번째 lvl만 렌더링되므로 다른 구성요소를 렌더링하려면 다이브를 사용해야 합니다.

위의 솔루션 중 어느 것도 나의 사용 예(커스텀 훅을 테스트하는 유닛)에 효과가 없었습니다.읽기 전용인 useLocation의 내부 속성을 덮어써야 했습니다.


\\ foo.ts

export const useFoo = () => {

   const {pathname} = useLocation();


\\ other logic

return ({
          \\ returns whatever thing here
       });
}

/*----------------------------------*/

\\ foo.test.ts

\\ other imports here

import * as ReactRouter from 'react-router';


Object.defineProperty(ReactRouter, 'useLocation', {
   value: jest.fn(),
   configurable: true,
   writable: true,
});

describe("useFoo", () => {


       it(' should do stgh that involves calling useLocation', () => {

           const mockLocation = {
               pathname: '/path',
               state: {},
               key: '',
               search: '',
               hash: ''
           };


         const useLocationSpy =  jest.spyOn(ReactRouter, 'useLocation').mockReturnValue(mockLocation)



          const {result} = renderHook(() => useFoo());
         
           expect(useLocationSpy).toHaveBeenCalled();


       });
 });

언급URL : https://stackoverflow.com/questions/59949052/how-do-you-mock-uselocation-pathname-using-shallow-test-enzyme-reactjs

반응형