인프런 커뮤니티 질문&답변

스고오이님의 프로필 이미지
스고오이

작성한 질문수

따라하며 배우는 리액트 테스트 [2023.11 업데이트]

not wrapped in act 경고

이미지가 안보인다 하셔서 다시 질문드립니다.

작성

·

297

·

수정됨

0

안녕하세요 선생님!
말씀 주신대로 7-6강 보고 왔지만... 혼자서는 문제의 원인 파악이 힘들어서 다시 재질문 드립니다 ㅠㅠ

로그를 확인해 보니 calculate.test.js에서 Fail이 발생되고 있지만, 원인 파악은 아직 못한 상태입니다 ㅠㅠ 레포지토리 주소도 같이 올려드립니다!

 PASS  src/pages/OrderPage/tests/Type.test.js (7.469 s)
 FAIL  src/pages/OrderPage/tests/Calculate.test.js (7.513 s)
  ● Console

    console.error
      Warning: An update to Type inside a test was not wrapped in act(...).
      
      When testing, code that causes React state updates should be wrapped into act(...):
      
      act(() => {
        /* fire events that update state */
      });
      /* assert on the output */
      
      This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
          at fn (D:\www\react-shop-test\src\pages\OrderPage\Type.js:8:17)

      17 |     try {
      18 |       const response = await axios.get(`http://localhost:5000/${orderType}`);
    > 19 |       setItems(response.data);
         |       ^
      20 |     } catch (err) {
      21 |       setError(true);
      22 |     }

      at printWarning (node_modules/react-dom/cjs/react-dom.development.js:86:30)
      at error (node_modules/react-dom/cjs/react-dom.development.js:60:7)
      at warnIfUpdatesNotWrappedWithActDEV (node_modules/react-dom/cjs/react-dom.development.js:27589:9)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:25508:5)
      at setItems (node_modules/react-dom/cjs/react-dom.development.js:17527:7)
      at loadItems (src/pages/OrderPage/Type.js:19:7)

  ● update product's total when products change

    expect(element).toHaveTextContent()

    Expected element to have text content:
      0
    Received:
      총 가격:

       6 |
       7 |   const productsTotal = screen.getByText("총 가격:", { exact: false });
    >  8 |   expect(productsTotal).toHaveTextContent("0");
         |                         ^
       9 |
      10 |   // const americaInput = await screen.findByRole("spinbutton", {
      11 |   //   name: "America",

      at Object.<anonymous> (src/pages/OrderPage/tests/Calculate.test.js:8:25)

 PASS  src/App.test.js (7.781 s)
  ● Console

    console.error
      Warning: An update to Type inside a test was not wrapped in act(...).
      
      When testing, code that causes React state updates should be wrapped into act(...):
      
      act(() => {
        /* fire events that update state */
      });
      /* assert on the output */
      
      This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
          at fn (D:\www\react-shop-test\src\pages\OrderPage\Type.js:8:17)
          at div
          at div
          at OrderPage
          at div
          at App

      17 |     try {
      18 |       const response = await axios.get(`http://localhost:5000/${orderType}`);
    > 19 |       setItems(response.data);
         |       ^
      20 |     } catch (err) {
      21 |       setError(true);
      22 |     }

      at printWarning (node_modules/react-dom/cjs/react-dom.development.js:86:30)
      at error (node_modules/react-dom/cjs/react-dom.development.js:60:7)
      at warnIfUpdatesNotWrappedWithActDEV (node_modules/react-dom/cjs/react-dom.development.js:27589:9)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:25508:5)
      at setItems (node_modules/react-dom/cjs/react-dom.development.js:17527:7)
      at loadItems (src/pages/OrderPage/Type.js:19:7)

    console.error
      Warning: An update to Type inside a test was not wrapped in act(...).
      
      When testing, code that causes React state updates should be wrapped into act(...):
      
      act(() => {
        /* fire events that update state */
      });
      /* assert on the output */
      
      This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
          at fn (D:\www\react-shop-test\src\pages\OrderPage\Type.js:8:17)
          at div
          at div
          at div
          at OrderPage
          at div
          at App

      17 |     try {
      18 |       const response = await axios.get(`http://localhost:5000/${orderType}`);
    > 19 |       setItems(response.data);
         |       ^
      20 |     } catch (err) {
      21 |       setError(true);
      22 |     }

      at printWarning (node_modules/react-dom/cjs/react-dom.development.js:86:30)
      at error (node_modules/react-dom/cjs/react-dom.development.js:60:7)
      at warnIfUpdatesNotWrappedWithActDEV (node_modules/react-dom/cjs/react-dom.development.js:27589:9)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:25508:5)
      at setItems (node_modules/react-dom/cjs/react-dom.development.js:17527:7)
      at loadItems (src/pages/OrderPage/Type.js:19:7)


Test Suites: 1 failed, 2 passed, 3 total
Tests:       1 failed, 4 passed, 5 total
Snapshots:   0 total
Time:        13.137 s
Ran all test suites related to changed files.


👇 기존 질문
https://www.inflearn.com/questions/985742

답변 2

0

John Ahn님의 프로필 이미지
John Ahn
지식공유자

안녕하세요 스고오이님~
현재 깃허브 주소에서 가져온 소스 코드를 기준으로 보았습니다.
우선 Calculate.text.js 는

import userEvent from "@testing-library/user-event";
import Type from "../Type";
import { render, screen } from "@testing-library/react";

test("update product's total when products change", async () => {
  render(<Type orderType="products" />);

  const productsTotal = screen.getByText("상품 총 가격:", { exact: false });
  expect(productsTotal).toHaveTextContent("0");

  const americaInput = await screen.findByRole("spinbutton", {
    name: "America",
  });

  userEvent.clear(americaInput);
  userEvent.type(americaInput, "1");
  // 여기는 먼저 context에서 가격 기능 구현 후 통과 시키면 됩니다.
  // expect(productsTotal).toHaveTextContent("1000");
});


이렇게 변경해주세요 ~

변경사항
1. userEvent 올바르게 import 해오기


Type.js는

import { useEffect, useState } from "react";
import axios from "axios";

import Options from "./Options";
import Products from "./Products";
import ErrorBanner from "../../components/ErrorBanner";

const Type = ({ orderType }) => {
  const [items, setItems] = useState([]);
  const [error, setError] = useState(false);

  useEffect(() => {
    loadItems(orderType);
  }, [orderType]);

  const loadItems = async (orderType) => {
    try {
      const response = await axios.get(`http://localhost:5000/${orderType}`);
      setItems(response.data);
    } catch (err) {
      setError(true);
    }
  };

  if (error) {
    return <ErrorBanner message="에러가 발생했습니다." />;
  }

  const ItemComponets = orderType === "products" ? Products : Options;

  const optionItems = items.map((item) => (
    <ItemComponets
      key={item.name}
      name={item.name}
      imagePath={item.imagePath}
    />
  ));

  return (
    <>
      <h2>주문 종류</h2>
      <p>하나의 가격</p>
      <p>상품 총 가격: 0</p>
      <div
        style={{
          display: "flex",
          flexDirection: orderType === "options" && "column",
        }}
      >
        {optionItems}
      </div>
    </>
  );
};

export default Type;


변경사항

1. 상품 총 가격: 0 <= 테스트에 따른 글자로 변경


Product.js 는

import React from "react";

const Products = ({ name, imagePath }) => {
  return (
    <div style={{ textAlign: "center" }}>
      <img
        style={{ width: "75%" }}
        src={`http://localhost:5000/${imagePath}`}
        alt={`${name} product`}
      />
      <form style={{ marginTop: "10px" }}>
        <label htmlFor={name} style={{ textAlign: "right" }}>{name}</label>
        <input
          id={name}
          style={{ marginLeft: 7 }}
          type="number"
          name="quantity"
          min="0"
          defaultValue={0}
        />
      </form>
    </div>
  );
};

export default Products;


변경 사항

1. input에 id 주기


이렇게 해주세요


스고오이님 !

처음에 테스트에 익숙하지 않을 때는
하나씩 따라서 작성하는 것 보다
먼저 한번 전체 강의를 보고 전체적으로 이해하는데 더 노력을 하면
더 효율적으로 공부하실수 있을것 같습니다 ^^

그리고 만약 에러가 하나 나면 바로 그 에러를 바로 처리하려고 하시면
에러가 여러개 쌓여있을 때 보다 훨씬 빠르게 에러의 이유를 캐치하고 처리하실수 있을 것 같습니다 !

감사합니다 화이팅!

스고오이님의 프로필 이미지
스고오이
질문자

친절하게 설명해 주셔서 정말 감사합니당ㅎㅎ
사실 강의는 처음 듣는거라 따라 적기 바빴는데 일단 먼저 전체적으로 수강 후 다시 진행해 봐야겠네용ㅎㅎ 감사합니다!

0

안녕하세요, 인프런 AI 인턴이에요.

코드를 보면 console.error에서 Warning: An update to Type inside a test라는 경고 메시지가 나옵니다. 이 경고 메시지는 테스트 코드에서 React 상태를 업데이트하는 부분이 act(...)로 감싸지지 않아서 발생한 것입니다. act(...) 함수는 테스트 중인 동작이 사용자가 실제로 볼 수 있는 동작을 반영하는지 확인하기 위해 사용됩니다.

해결 방법으로는 테스트 코드에서 React 상태 업데이트 부분을 act(...)로 감싸는 것입니다. act(...) 함수는 다음과 같이 사용할 수 있습니다.

act(() => {
  setItems(response.data);
});

이렇게 코드를 수정하면 경고 메시지가 사라지고 테스트가 성공적으로 실행될 것입니다. 이 방법을 사용하여 calculate.test.js 파일에서 발생하는 오류를 해결해보세요. 오류의 원인이 되는 코드를 파악하여 수정하면 테스트가 통과할 수 있을 것입니다.

더 자세한 내용은 React의 공식 문서인 https://reactjs.org/link/wrap-tests-with-act를 참고해주세요.

문제 해결에 도움이 되었길 바라며, 추가로 궁금한 점이 있다면 언제든지 물어보세요. 좋은 결과 있기를 바라요!

스고오이님의 프로필 이미지
스고오이

작성한 질문수

질문하기