ziglog

    Search by

    리액트 훅 테스트

    August 1, 2021 • ☕️ 2 min read

    react hook test


    custom hook으로 작성한 react query의 동작을 테스트하기 위해 react-hooks-testing-library를 사용했다. 기본적으로 renderHook이라는 메서드를 제공하여, hook 테스트를 위해 별도의 컴포넌트를 작성하여 hook을 호출할 필요가 없다. 내부적으로 HTTP request를 사용하는 hook이나, 복잡한 컴포넌트 로직 내에서 동작하는 hook의 경우에 react-hooks-testing-library를 사용하여 간단하게 테스트를 진행해볼 수 있다.

    renderHook에 테스트하고자 하는 hook 함수를 넘겨주고, 반환값인 result를 이용하여 hook 호출의 성공 여부(isSuccess)와 반환된 데이터(data)를 검사한다.

    Copy
    import { renderHook } from "@testing-library/react-hooks";
    
    describe("useRecentFeeds 테스트", () => {
      it("최신 피드를 불러올 수 있다.", async () => {
        const { result, waitFor } = renderHook(() =>
          useRecentFeeds({ filter: FilterType.PROGRESS })
        );
    
        await waitFor(() => result.current.isSuccess);
    
        expect(result.current.data).toEqual(mockFeeds);
      });
    });

    hook 실행 후 일정 시간이 지나야 통과되는 비동기적인 실행이라면, renderHook에서 반환되는 waitForNextUpdate 함수를 통해 hook 내부 로직에서 변화가 발생하는 시점까지 기다린 후 expect문을 실행할 수 있다.

    Copy
    import { renderHook } from "@testing-library/react-hooks";
    
    describe("useOAuthLogin 테스트", () => {
      it("github으로부터 액세스 토큰을 받아올 수 있다.", async () => {
        const { waitForNextUpdate } = renderHook(() => useOAuthLogin("github"));
    
        await waitForNextUpdate();
    
        expect(localStorage.getItem("accessToken")).not.toBeNull();
      });
    
      it("google로부터 액세스 토큰을 받아올 수 있다.", async () => {
        const { waitForNextUpdate } = renderHook(() => useOAuthLogin("google"));
    
        await waitForNextUpdate();
    
        expect(localStorage.getItem("accessToken")).not.toBeNull();
      });
    });

    테스트에 사용된 hook들은 모두 서버 데이터를 가져오는 react query 코드였는데, 이때 msw(mock-service-worker)를 이용하여 실제 서버로 가는 요청을 가로채 지정한 응답을 반환해줬다. 실제 서버는 언제든지 터지거나 사이드 이펙트가 발생할 수 있기 때문에, 서버를 mocking하여 기대하는 결과값이 나오는지 검사해준다.

    Copy
    rest.get(`${BASE_URL.production}/login/oauth/:type/token`, (req, res, ctx) => {
      return res(
        ctx.status(200),
        ctx.json({
          accessToken: 'mock-access-token-abc-123',
        }),
      );
    }),

    이밖에도 act 함수를 통해 hook 내부에 정의한 함수를 실행시켜줄 수도 있으며, renderHook에 전달되는 hook에 인자를 넘겨줄 수도 있다. 여러모로 유용하게 hook test를 작성할 수 있다!


    Ref


    Relative Posts:

    프론트엔드 성능 분석 & 기본 성능 개선

    August 14, 2021

    react query에서 debounce 쓰기

    July 24, 2021

    zigsong

    지그의 개발 블로그

    RotateLinkImg-iconRotateLinkImg-iconRotateLinkImg-icon