본문 바로가기
⛔️ Error

react-testing-library 의 "not wrapped in act(...)" Error

by ChaeLOTUS 2023. 12. 4.
728x90

 

 

코딩악마 님의 jest 강의를 보면서 userEvent 관련 실습을 진행 중이었습니다.

간단하게 click 이벤트의 test code를 작성하고 있었는데 왜인지 터미널에 빨간 글씨로 error가 뜨더라구요..

 

해당 error의 내용은 이렇습니다.

console.error
경고: 테스트 내부의 로그인에 대한 업데이트가 실행되지 않았습니다(...).

테스트 시 React 상태 업데이트의 원인이 되는 코드를 act(...)로 래핑해야 합니다:

     act(() => {
        /* fire events that update state */
      });
      /* assert on the output */

이것은 사용자가 브라우저에서 볼 수 있는 동작을 테스트하는 것을 보장합니다. 자세한 내용은 https://reactjs.org/link/wrap-tests-with-act 에서 확인하십시오

 

 

이 문제에 대한 원인은 크게 3가지로 분류됩니다.

 

1. 비동기 업데이트

: 컴포넌트가 비동기 API 호출하는 경우

=> react-testing-library에서 waitFor이라는 비동기 유틸리티를 사용하여 컴포넌트가 업데이트가 완료될 때까지 기다릴 수 있습니다.

2. Fack Timer

: 컴포넌트 내에 setTimeout 혹은 setInterver 사용하는 경우

=> 테스트 코드에서 타이머를 jest.useFackTimers로 mocking 하고 jest.advanceTimersByTime(msToRun)로 실행할 수 있습니다.

=> 위와 마찬가지로 컴포넌트를 업데이트하고 있기 때문에 act()로 감싸주어야 에러가 나지 않습니다.

3.  렌더링/업데이트 전에 테스트가 종료됨

: 주로 로딩 상태에서 조건문을 통해 렌더링 하는 코드인 경우

=> 1번과 마찬가지로 waitFor로 기다려야 합니다.

 

 

Login.js

import {useState} from 'react';

export default function Login(){
    const [isLogin, setIsLogin] = useState(false);

    const onClickHandler = () => {
        setIsLogin(!isLogin);
    }

    return(
        <button onClick={onClickHandler}>{isLogin ? 'Logout' : 'Login'}</button>
    )
}

 

Login.test.js

import {render,screen,waitFor} from '@testing-library/react';
import Login from './Login';
import userEvent from '@testing-library/user-event';

describe('Login Teat',()=>{
    test('처음에는 Login 버튼이 있다.',()=>{
        render(<Login/>);
        const btnEl = screen.getByRole('button');
        expect(btnEl).toHaveTextContent('Login');
    })

})

const user = userEvent.setup();
test('한 번 클릭하면 Logout 버튼이 된다.',async ()=>{
    render(<Login/>);
    const btnEl = screen.getByRole('button');
 
    await waitFor(()=>{
        user.click(btnEl);
        expect(btnEl).toHaveTextContent('Logout')
    })
})
728x90

댓글