首页 > 解决方案 > 使用 MSW 测试 React-query,并将数据传递给子组件

问题描述

我正在使用 React-query 并尝试对其进行测试,在父组件中调用数据并传递给子组件以呈现项目列表。我已经设置了 MSW,但是当我尝试测试时:

const queryClient = new QueryClient()

it('Should give a response', async () => {
    render(<QueryClientProvider client={queryClient}><Component /></QueryClientProvider>);
    expect(await screen.findByTestId('test-data')).toBeInTheDocument();
})

我明白了:

Unable to find an element by: [data-testid="test-data"]

<body>
  <div>
    <div
      class="mt-5"
    >
      Loading data ...
    </div>
  </div>
</body>

父组件是这样的:

const Component1: React.FunctionComponent = () => {
    const [fetchData, setFetchData] = React.useState<IData[]>([]);

    const queryKey = 'mainData';

    const getData = async (): Promise<any> => {
            await new Promise(resolve => setTimeout(resolve, 1000))
            const response = await axios.get(`xxxxxxx}`).then(res => res.data);
            return response;
    }

    const { data: result, status, isRefetching, error, refetch }: any = useQuery(queryKey, getData,
        {
            refetchOnWindowFocus: true,
            staleTime: 0,
            cacheTime: 0,
            refetchInterval: 0,
        }
    );
 
    return (
        <>
            {status === 'error' && (
                <div className="mt-5">{error.message}</div>
            )}
            {status === 'loading' && (
                <div className="mt-5">Loading data ...</div>
            )}
            {status === 'success' && (
                <div className="row dashboard">
                    <ChildComponent data={fetchData} data-testid="test-data"/> // data passed to this component
                    <br />
                </div>
            )}
            {isRefetching ? 'Updating...' : null} 
        </>
    )
};

export default Component1;

设置测试:

import '@testing-library/jest-dom';

import { server } from './mocks/server'
// Establish API mocking before all tests.

beforeAll(() => server.listen())
// Reset any request handlers that we may add during the tests,
// so they don't affect other tests.

afterEach(() => server.resetHandlers())

// Clean up after the tests are finished.
afterAll(() => server.close())

处理程序

import { rest } from 'msw';

export const handlers = [
    rest.get('https://xxxxxxxx', (req, res, ctx) => {
        return res(
            ctx.json([
                {
                    "titleNumber": 499,
                    "model": "Yes Model",
                },
                {
                    "titleNumber": 434,
                    "model": "No Model",
                },
            ])
        );
    }),
];

服务器

import { setupServer } from 'msw/node'
import { handlers } from './handlers'
export const server = setupServer(...handlers)

我在错误的地方测试吗?

标签: reactjsreact-querymsw

解决方案


更新的答案

好的,这是一个非常奇怪的问题。我复制了它并得到了同样的东西,即使它不应该。我认为问题可能与反应查询和测试有关,而不是与 msw 有关。为了解决它,我只是开玩笑说useFakeTimers然后它起作用了

describe('should return data', () => {
    beforeEach(() => {
        jest.useFakeTimers();
    });

    it('Should give a response', async () => {
        render(
            <QueryClientProvider client={queryClient}>
                <App />
            </QueryClientProvider>
        );
        expect(await screen.findByTestId('test-data')).toBeInTheDocument();
        // screen.debug();
    });
});

我认为这个问题是因为你data-testid="test-data"作为一个道具传递,ChildComponent我猜你没有在组件内部使用它,这意味着它实际上没有附加到任何 DOM 元素。这可以解释为什么它说它找不到元素,因为除非你在里面使用它,ChildComponent否则它不会被使用。

尝试将其添加到作为 don 节点而不是组件的元素中,例如包含它的 div。

{status === 'success' && (
    <div className="row dashboard" data-testid="test-data">
        <ChildComponent data={fetchData} />
        <br />
    </div>
)}

推荐阅读