【问题标题】:Test fails with Content.Provider in React-Testing-LibraryReact-Testing-Library 中的 Content.Provider 测试失败
【发布时间】:2022-01-03 11:35:27
【问题描述】:

这是我要测试的反应类。 我使用Content.Provider 来保持全局状态。 在我的测试文件中,我将其命名为<Store>

import { useEffect, useContext } from "react";
import { Context } from '../../config/Store';

const ProjectPage = () => {
    const [globalState, dispatch] = useContext(Context);

    useEffect(() => {
        getAllProjectData();
    }, []);

    const getAllProjectData = async () => {
        console.log('### getAllProjectData - ProjectPage.jsx')
        try {
            const data = await getProjectData();
            dispatch({ type: 'setIsLoaded', payload: true })
            dispatch({ type: 'setError', payload: false })
            dispatch({ type: 'setProjectDetails', payload: data })
        } catch (error) {
            console.log("### Error: ", error)
            dispatch({ type: 'setProjectDetails', payload: null })
            dispatch({ type: 'setIsLoaded', payload: true })
            dispatch({ type: 'setError', payload: true })
        }
    }

    if (globalState.error) {
        return <div><ErrorPage /></div>;
    } else if (!globalState.isLoaded) {
        return <div className="spinnerContainer" data-testid="spinnerContainer" 
                  <CircularProgress className="spinner" color="error" size="3rem" thickness={7} />
               </div>;
    } else {
        return <div id="projectToolbar" data-testid="projectTabBar" className="container-fluid"></div>;
    }
}

export default ProjectPage;

然后我有这个test.js 文件,其中第一个测试成功,第二个测试失败。

import Store from '../../config/Store';
import ProjectPage from './ProjectPage';
import { render } from '@testing-library/react';

test('renders the spinner before the project page', () => {
    const { getByTestId } = render(<Store><ProjectPage /></Store>);
    const spinnerContainer = getByTestId("spinnerContainer");
    expect(spinnerContainer).toBeInTheDocument();
});

test.only('renders the project tab bar', async () => {
    render(<Store><ProjectPage /></Store>);
    const projectTabBar = await waitFor(async () => await screen.findByTestId("projectTabBar"))
    expect(projectTabBar).toBeInTheDocument();
});

在我的记录器中,测试显示如下:

正如您所见,测试失败是因为data-testid="projectTabBar" 不在文档中,而微调器在那里。我知道发生这种情况是因为组件没有呈现数据,但我不明白为什么会发生这种情况以及如何解决它。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript reactjs jestjs react-testing-library react-testing


    【解决方案1】:

    您的第一个测试和第二个测试的设置看起来相同,因此预计它们将返回相同的结果。您看到微调器的原因是在您执行断言时,您的数据仍在加载。您可以采取几种方法。

    1. 测试Store 的真正实现,这包括等待您的getAllProjectData 函数完成并重新渲染组件。这可能导致不稳定和长时间运行的测试,但会端到端测试组件。查看testing library async functions documentation 了解如何执行此操作,并特别注意超时。

    2. getAllProjectData 函数和useEffect 抽象为自定义钩子,并在组件中使用它。这允许您在测试中模拟自定义钩子的实现,并同步设置Store 的加载、错误或数据状态。请注意,您仍然需要等待 projectTabBar 出现,因为在初始渲染时,Store 不会被初始化,但等待应该是短暂且一致的,这会导致更快和更少的不稳定测试,但是您还需要单独为自定义挂钩编写测试。

    【讨论】:

    • 很好的解释和提示在哪里看。我根据提供的文档使用 async/await 更改了我的测试,并在问题中更新了我的测试。发生的情况是 getAllProjectData 在现实中被调用,但不是在测试中。
    • 尝试将const projectTabBar = await waitFor(async () =&gt; await screen.findByTestId("projectTabBar")) 更改为const projectTabBar = await screen.findByTestId("projectTabBar", { timeout: 10000})。不需要waitFor,默认超时只有1秒,可能不够长。
    猜你喜欢
    • 1970-01-01
    • 2019-05-21
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多