#reactjs #unit-testing #jestjs #react-testing-library
Вопрос:
Я довольно новичок в библиотеке реактивного тестирования и в целом в тестировании. Я хочу протестировать компонент, который извлекает данные из API в useEffect hook. Затем он сохраняет его в локальном состоянии. Он отображает эти данные массива с помощью array.map, но я получаю Error: Uncaught [TypeError: Cannot read properties of undefined (reading 'map')]
ошибку. Я, вероятно, ошибаюсь в своем наборе тестов, я много исследовал, но не смог это исправить.
import React from 'react'; import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom' import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { OnePiece } from '.'; const server = setupServer(rest.get('server http address', (req, res, ctx) =gt; { const totalData = [ { name: "doffy", price: 100, image: "image url" }, { name: "lamingo", price: 500, image: "image url" } ]; return res( ctx.status(200), ctx.json({ data: { crew: totalData } }) ) })) beforeAll(() =gt; server.listen()); afterAll(() =gt; server.close()); beforeEach(() =gt; server.restoreHandlers()); //console.log("mocking axios", axios) describe('OnePiece', () =gt; { test('fetches the data from the API and correctly renders it', async () =gt; { //Here's probably where i fail. Please someone tell me the right way :) await render(lt;OnePiece /gt;) const items = await screen.findAllByAltText('product-image'); expect(items).toHaveLength(2); // screen.debug() }) })
А ниже приведены части кода useEffect и totalData.map в компоненте:
const [totalData, setTotalData] = useState([]); const [crew, setCrew] = useState('straw-hat-pirates'); useEffect(() =gt; { let isApiSubscribed = true; const getOpData = async () =gt; { const getCrews = await axios.get('http address'); if (isApiSubscribed) { let data = getCrews.data; data = data[crew]; // console.log("data", data); setTotalData(data); } } getOpData(); return () =gt; { isApiSubscribed=false; } }, [crew]) ......... //in the return part lt;ProductsWrappergt; {totalData.map((product, index) =gt; lt;ProductCard key={index} name={product.name} price={product.price} imageUrl={product.image} /gt; )} lt;/ProductsWrappergt;
Ответ №1:
Как я и предсказывал, проблема заключалась в асинхронной выборке данных. В настоящее время setTimeout для меня более чем достаточно, но если кто-то увидит это в будущем, вы можете поискать метод waitFor библиотеки тестирования реакции. Вот фиксированная часть:
describe('OnePiece', () =gt; { test('fetches the data from the API and correctly renders it', async () =gt; { render(lt;OnePiece /gt;) setTimeout(async () =gt; { const items = await screen.findAllByAltText('product-image'); expect(items).toHaveLength(2); }, 4000) //screen.debug() }) })