【问题标题】:Jest + React Testing Library: waitFor is not workingJest + React 测试库:waitFor 不工作
【发布时间】:2021-07-17 14:46:15
【问题描述】:

我正在使用 Jest 和 React 测试库为我的 React JS 应用程序编写单元测试。我正在尝试测试异步功能。但它不起作用。

这是我的测试

import React from 'react';
import "regenerator-runtime/runtime"
import {render, waitFor, fireEvent, screen} from '@testing-library/react';
import {DonorSelect} from "../../src/components";
import MockAdapter from "axios-mock-adapter";
import Axios from 'axios';
import vars from "../configVars";
import {searchUsersResponse} from "../mock/apiResponse";
import { act } from "react-dom/test-utils"

test ("DonorSelect Component", async () => {
   let selectedUser = null;
   let users = [ ];
   let inputValue=""

    //mock the users api endpoint
    let mock = new MockAdapter(Axios);
    mock.onGet(`${vars.baseApEndpoint}/users?keyword=client`)
        .reply(200, searchUsersResponse)

    await act(async() => await render(
        <DonorSelect
            id={"user_select"}
            onSelect={(user, displayText) => {
                selectedUser = { ...user }
            }}
            onInputChange={(textFieldValue) => {
                inputValue = textFieldValue;
            }}
            onUsersFetched={(userItems) => {
                users = [ ...userItems ]
            }}
            onChange={(name, value) => {

            }}
            label={"Search User"}
            placeholder={"Please, select a user."}
            name={"user"}
            value={selectedUser!=null? selectedUser.id:""}
            inputValue={inputValue}
        />
    ))

    //assert that input is rendered
    expect(screen.getByTestId("user_select_input")).toBeTruthy()
    fireEvent.change(screen.getByTestId("user_select_input"), {
        target: { value: "client" }
    })
    fireEvent.focus(screen.getByTestId("user_select_input"))

    await waitFor(() => {
        //assert that if the label is rendered
        expect(screen.getByTestId("user_select_label")).toBeTruthy()
        // assert that input is rendered
        expect(screen.getByTestId("user_select_user_item_0")).toBeTruthy()
    })
})

正如您在测试中看到的那样,最后一个 expect() 不起作用

expect(screen.getByTestId("user_select_user_item_0")).toBeTruthy()

总是失败。该组件所做的是,当输入值更改并专注于输入时,它将发出 api 请求并呈现项目。该组件按预期工作。我已经对其进行了全面测试。但它只是在测试中不起作用。我的代码有什么问题,我该如何解决?

【问题讨论】:

  • 请提供stackoverflow.com/help/mcve。尚未确认该组件是否按预期工作。考虑到测试失败,很可能不会。
  • 嗨,它按预期工作。我刚刚包含了组件的代码。请看一看。 @EstusFlask
  • 组件体积大,故障点多,需要重构成几个。渲染函数是一种反模式,它可以是一个单独的组件。很难阅读,这减少了有人有足够的时间在 SO 上为您调试它的机会。据我所知,影响断言失败的兴趣点是(props.inputValue =="" || users.length&lt; 1)。可以看出您在测试中提供了 inputValue。但看起来用户是空的。您应该已经对 user-autocomplete-users-wrapper 进行了测试,以使测试更加具体。

标签: reactjs jestjs react-testing-library


【解决方案1】:

默认的waitFor超时时间为1000ms。

如果您在没有模拟的情况下调用真正的端点(建议使用模拟,例如使用 msw),这可能需要 1 秒以上的时间才能执行。

这会导致超时,waitFor会抛出错误。

如果你不想模拟端点,拦截它并返回一个测试值,它应该在 1 秒以下,你也可以延长超时时间,等待真正的 api 调用被执行和解决:

await waitFor(() => {
        //assert that if the label is rendered
        expect(screen.getByTestId("user_select_label")).toBeTruthy()
        // assert that input is rendered
        expect(screen.getByTestId("user_select_user_item_0")).toBeTruthy()
    }
,{timeout: 4000}) // this will now wait 4 secs for the execution, but you should see what works for you.

【讨论】:

  • 考虑到测试已经模拟了一个请求,timeout 可能不相关。
猜你喜欢
  • 2021-06-14
  • 1970-01-01
  • 2020-07-19
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
  • 2021-05-26
  • 2020-02-09
  • 2020-04-21
相关资源
最近更新 更多