Testing Library - act는 언제 써야 할까?

브라우저 상에서의 React와 비슷한 방식으로 테스트할 수 있게 해주는 act API 알아보기

2024-06-16에 씀
프론트엔드 테스트 가이드 시리즈의 다른 글
  1. jest로 비동기 함수 테스트하기
  2. Storybook Interaction Test를 활용한 바텀시트 시각적 테스트
  3. React Testing Library로 테스트할 요소를 선택하는 방법
  4. 프론트엔드 TDD 튜토리얼 with React & Testing Library
  5. Testing Library - act는 언제 써야 할까?

React가 브라우저에서 동작하는 것과 흡사한 환경에서 테스트를 수행할 수 있도록, React에서는 act라는 API를 제공하고 있다.

UI 테스트를 수행하기 위해서는 렌더링, 이벤트 발생, 데이터 불러오기 등 UI와 상호작용하는 작업이 수행되어야 하는 경우가 있다. 이로 인해 발생하는 컴포넌트 렌더링이나 데이터 갱신은 동기적으로 처리될 수도 있지만, 리액트가 내부적으로 스케줄링하여 비동기적으로 처리하게 될 수도 있다. 따라서 작업의 결과가 언제 적용될 것인지는 리액트가 어떻게 동작할지에 달려 있다.

act가 하는 일은 위와 같이 리액트의 내부 동작에 영향을 받는 코드들이 assertion을 수행하기 전에 모두 완료되게 하는 것이다. 리액트 동작과 관련 있는 코드를 act 함수로 감싸서 호출하면 act는 Promise를 반환하고, 이 Promise는 act가 감싸고 있는 코드가 모두 처리되어 DOM에 반영되기 직전에 resolve된다.

React Testing Library의 경우

React Testing Library는 React에서 제공하는 act를 감싼 같은 이름의 함수를 제공하고 있다. 뿐만 아니라, 제공하는 API 중 render, fireEvent 등의 함수에서도 내부적으로 act를 사용해 구현하고 있다. 따라서 단순 React API를 사용했다면 act로 감싸야 하겠지만, React Testing Library를 사용하는 경우 render 호출이나 이벤트 발생 코드는 act로 감싸지 않아도 된다.

그렇지만 React Testing Library를 거치지 않고 상태 변경이 일어나는 경우에는 코드 호출 시 act로 감싸 주어야 한다.

1const useBoolean = (initialState = false) => {
2 const [value, setValue] = useState(initialState)
3
4 const toggle = () => setValue(prev => !prev)
5
6 return { value, setValue, toggle }
7}
8
9test('toggle을 호출하면 값이 반대가 된다', () => {
10 const { result } = renderHook(() => useBoolean(false))
11
12 // act로 감싸주지 않으면 expect 시점에 값이 갱신되어 있지 않다
13 act(() => result.current.toggle());
14
15 expect(result.current.value).toBe(true);
16})

정리하자면 아래와 같은 기준으로 act를 감싸면 된다.

참고한 글

프론트엔드 테스트 가이드 시리즈의 다른 글
  1. jest로 비동기 함수 테스트하기
  2. Storybook Interaction Test를 활용한 바텀시트 시각적 테스트
  3. React Testing Library로 테스트할 요소를 선택하는 방법
  4. 프론트엔드 TDD 튜토리얼 with React & Testing Library
  5. Testing Library - act는 언제 써야 할까?
프로필 사진

조예진

이전 포스트
Jotai Atom의 스코프 관리하기
다음 포스트
FSD 살펴보기