조롱 redux useSelector-hook

10529 단어 reactreduxjesttesting
업데이트
일부 사람들이 의견에서 지적한 것처럼 공식적인 사용 방법 RTL with redux이 있지만 제대로 작동하지 않았습니다.
내가 무능하거나 내 프로젝트에서 문제를 일으키는 무언가가 있을 수 있으므로 모의useSelector에 대한 내 솔루션이 여전히 사용될 수 있습니다. 🙄

최근에 저는 마침내 Enzyme에서 React testing library (RTL)으로 전환했습니다. 즉, Enzyme이 제안한 것처럼 shallow를 사용하여 구성 요소를 렌더링하는 대신 React 테스트 라이브러리를 사용하면 Enzymesmount와 같이 전체 구성 요소와 하위 구성 요소가 렌더링됩니다. .

Redux를 사용할 때 HOC 대신 후크를 사용하는 것과 결합된 RTL로의 전환으로 인해 새로운 구성 요소 테스트를 많이 작성할 수 있었지만 Redux에서 useSelector -hook을 사용하려고 여러 번 다른 응답을 기대하면서 몇 가지 문제가 발생했습니다.

다음과 유사한 호출을 수행하는 검색 구성 요소로 테스트하고 싶었던 구성 요소:

const MySearchComponent = () => {
  const { query, rows } = useSelector((state) => 
    state.config);

  const {
      items,
      hasMore
    } = useSelector((state) => state.search);

  return (...)
}

useSelector는 상태를 인수로 사용하고 상태 조각을 반환하는 콜백 함수를 사용합니다.

따라서 구성 요소를 테스트하려고 할 때 첫 번째 접근 방식은 두 가지 다른 응답을 보내는 것이었습니다.

jest.mock("react-redux", () => ({
  ...jest.requireActual("react-redux"),
  useSelector: jest.fn()
    .mockReturnValueOnce(mockConfigState)
    .mockReturnValueOnce(mockSearchState)
}));

describe("MySearchComponent", () => {
  afterEach(() => {
    useSelector.mockClear();
  });
  it("should render", () => {
    const { getByTestId } = render(<MySearchComponent />);
    expect(...)
  });
});



자식 구성 요소도 useSelector를 호출하여 충돌한다는 것을 깨달을 때까지 잘 작동했습니다. 😱

필요한 모든 가능한 선택자를 지원하지만 여전히 테스트별로 수정할 수 있는 무언가가 필요하다는 것을 알았습니다.
나는 모의 상태를 준비했지만 그것을 변경하고 주입하는 방법은 없었습니다.
내가 jest.fn().mockImplementation를 만날 때까지 ...

내 문제에 대한 해결책


useSelector는 콜백을 인수로 사용하며 내가 해야 할 일은 내 모든 구성 요소 요구 사항을 충족하고 나머지는 구현된 대로 수행하는 호환 가능한 상태로 해당 콜백을 호출하는 것이었습니다.

jest.mock("react-redux", () => ({
  ...jest.requireActual("react-redux"),
  useSelector: jest.fn()
}));

describe("MySearchComponent", () => {
  beforeEach(() => {
    useSelector.mockImplementation(callback => {
      return callback(mockAppState);
    });
  });
  afterEach(() => {
    useSelector.mockClear();
  });
  it("should render a query", () => {
    const { getByTestId } = render(<MySearchComponent />);
    expect(getByTestId("query_testId").textContent)
      .toEqual(mockAppState.config.query)
  });
  it("should not render if query is empty", () => {
      const localMockState = {
        ...mockAppState,
        config: {
          ...mockShoppingState.config,
          query: ""
        }
      };
      useSelector.mockImplementation(callback => {
        return callback(localState);
      });
    const { queryByTestId } = render(<MySearchComponent />);
    expect(queryByTestId("query_testId")).toBeNull();
  });
});



그래서 위의 코드에서 저는 react-redux npm 패키지에서 모의useSelector하고 모의된 상태를 인수로 사용하여 주어진 콜백 함수를 실행하는 함수로 바꿉니다. 이것은 모든 테스트 전에 수행됩니다.

두 번째 테스트에서는 해당 테스트에만 사용할 두 번째 모의 상태를 생성하므로 기본 모의 상태 대신 업데이트된 상태를 사용하도록 재정의useSelector합니다.

이별의 말



이것이 누군가가 자신의 코드를 테스트하는 방법과 jest 및 RTL과 같은 도구로 달성할 수 있는 작업에 대해 조금 더 배우는 데 도움이 되었기를 바랍니다.

모든 오타는 제가 직접 작성한 것이며 질문이 있거나 이해가 되지 않는 사항이 있으면 댓글을 남겨주세요.

좋은 웹페이지 즐겨찾기