开发者问题收集

如何使用 react-testing-library 和 jest 测试在 useEffect 中获取数据并将其存储在状态中的组件?

2021-11-23
3345

我对 react-testing-library 和一般测试还不太熟悉。我想测试一个组件,该组件从 useEffect 钩子中的 API 中获取数据。然后将其存储在本地状态中。它使用 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) => {
        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(() => server.listen());
    afterAll(() => server.close());
    beforeEach(() => server.restoreHandlers());

    //console.log("mocking axios", axios)
    describe('OnePiece', () => {
        
        test('fetches the data from the API and correctly renders it', async () => {
            //Here's probably where i fail. Please someone tell me the right way :) 
            await render(<OnePiece />)
            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(() => {
    let isApiSubscribed = true;
    const getOpData = async () => {
        const getCrews = await axios.get('http address');
        if (isApiSubscribed) {
            let data = getCrews.data;
            data = data[crew];
            // console.log("data", data);
            setTotalData(data);
        }
    }
    getOpData();
    return () => {
        isApiSubscribed=false;
    }
}, [crew])
.........

//in the return part
 <ProductsWrapper>
            {totalData.map((product, index) =>
                <ProductCard key={index} name={product.name} price={product.price} imageUrl={product.image} />
            )}
        </ProductsWrapper>
1个回答

正如我所料,问题出在异步数据获取上。目前 setTimeOut 对我来说已经足够了,但如果以后有人看到这个问题,你可以查找 react-testing-library 的 waitFor 方法。 这是修复的部分:

  describe('OnePiece', () => {
      test('fetches the data from the API and correctly renders it', async () => {
          render(<OnePiece />)
          setTimeout(async () => {
              const items = await screen.findAllByAltText('product-image');
              expect(items).toHaveLength(2);
            }, 4000)
            //screen.debug()
        })
    })
dumblessar
2021-11-23