본문 바로가기
시작/TIL(Today I Learned)

React Testing Tutorial(9) - findBy

by 백씨네 2024. 9. 18.
 

findBy

React Testing Library에서 DOM요소를 찾을 때 많이 쓰이는 메서드 중 하나인 findBy는 비동기적으로 요소를 찾을 때 유용하다.
API 호출이나, 타이머처럼 일정 시간이 지난 후에 렌더링 되는 요소를 테스트할 때 주로 사용된다.

findBy는 Promise를 반환한다. 지정된 시간 내에 해당 요소를 찾으면 resolve, 그렇지 않으면 reject 된다.

 

사용시기

  • 데이터 패칭 이후 나타나는 요소
  • setTimeout, setInterval 등으로 일정 시간이 지난 후 나타나는 요소
  • 상태 변경으로 인한 렌더링 결과물

findBygetBy는 유사하지만 비동기 요소를 기다린다는 점에서 다르다.
promise를 반환하기 때문에 주로 async/await와 함께 사용된다.

const element = await findByText("로딩 완료")

작성 예시

import React, { useEffect, useState } from "react"

const UserProfile = () => {
    const [loading, setLoading] = useState(true)
    const [user, setUser] = useState("")

    useEffect(() => {
        setTimeout(() => {
            setUser("홍길동")
            setLoading(false)
        }, 2000)

    }, [])

    if (loading) {
        return <div>로딩 중...</div>
    }
    return <div>사용자 이름: {user}</div>
}

export default UserProfile

 

 

import { render, screen } from '@testing-library/react';
import UserProfile from './UserProfile';

test('사용자 이름을 API 호출 후 렌더링한다', async () => {
  render(<UserProfile />);
  expect(screen.getByText('로딩 중...')).toBeInTheDocument();
  const userNameElement = await screen.findByText('사용자 이름: 홍길동');
  expect(userNameElement).toBeInTheDocument();
});

위의 코드는 실패한다.

이유는 기본적으로 findBy가 기다리는 시간은 1000ms로 설정되어 있기 때문이다.
하지만 작성한 컴포넌트는 2000ms 뒤에 상태를 바꾸는 동작을 하기 때문에 실패하는 코드가 된다.

이를 해결하기 위해서 findBy~ ()의 3번째 인자값을 이용해서 시간을 지정할 수 있다.

 

const userNameElement = await screen.findByText("사용자 이름: 홍길동",{},{
    timeout:2000
})

다시 작성된 테스트코드를 보면 timeout을 이용해서 기다리는 시간을 늘려 2초를 기다리는 테스트 코드로 만들었다. 그 결과 해당 테스트 코드는 통과할 수 있게 되었다.

댓글