React 测试库不更新状态

2024-03-05

我的组件:

import React from 'react'

const TestAsync = () => {
  const [counter, setCounter] = React.useState(0)

  const delayCount = () => (
    setTimeout(() => {
      setCounter(counter + 1)
    }, 500)
  )
  
return (
  <>
    <h1 data-testid="counter">{ counter }</h1>
    <button data-testid="button-up" onClick={delayCount}> Up</button>
    <button data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button>
 </>
    )
  }
  
  export default TestAsync

我的测试文件:

describe("Test async", () => {
  it("increments counter after 0.5s", async () => {
    const { getByTestId, getByText } = render(<TestAsync />);

    fireEvent.click(getByTestId("button-up"));

    const counter = await waitForElement(() => getByTestId("counter"));

    expect(counter).toHaveTextContent("1");
  });
});

运行测试文件后,我收到错误消息:

Expected element to have text content:                                                          
      1                                                                                             
Received:                                                                                       
      0

我有点困惑为什么我使用waitForElement获取元素,但为什么元素仍然具有旧值?

React-testing-library 版本 9.3.2


首先,waitForElement已被弃用。用一个find*查询(首选:https://testing-library.com/docs/dom-testing-library/api-queries#findby https://testing-library.com/docs/dom-testing-library/api-queries#findby)或使用waitFor反而:https://testing-library.com/docs/dom-testing-library/api-async#waitfor https://testing-library.com/docs/dom-testing-library/api-async#waitfor

现在,我们使用waitFor:

waitFor可能会多次运行回调,直到达到超时。

您需要将断言语句包装在回调的内部waitFor。以便waitFor可以多次运行回调。如果你把expect(counter).toHaveTextContent('1');外部和之后的声明waitFor语句,那么它只运行一次。断言运行时 React 尚未更新。

为什么RTL会多次运行回调(超时前每隔一段时间运行回调)?

RTL use 变异观察者 https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver要监视对 DOM 树所做的更改,请参阅here https://github.com/testing-library/dom-testing-library/blob/main/src/wait-for.js#L110。请记住,我们的测试环境是jsdom,它支持MutationObserver, see here https://github.com/jsdom/jsdom/issues/639#issuecomment-816851899.

这意味着当 React 更新状态并将更新应用到 DOM 时,可以检测到 DOM 树的更改,并且 RTL 将再次运行回调(包括断言)。当 React 组件状态被应用并变得稳定时,回调的最后一次运行将被视为测试的最终断言。如果断言失败,则报告错误,否则测试通过。

所以工作示例应该是:

index.tsx:

import React from 'react';

const TestAsync = () => {
  const [counter, setCounter] = React.useState(0);

  const delayCount = () =>
    setTimeout(() => {
      setCounter(counter + 1);
    }, 500);

  return (
    <>
      <h1 data-testid="counter">{counter}</h1>
      <button data-testid="button-up" onClick={delayCount}>
        Up
      </button>
      <button data-testid="button-down" onClick={() => setCounter(counter - 1)}>
        Down
      </button>
    </>
  );
};

export default TestAsync;

index.test.tsx:

import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';
import TestAsync from '.';
import '@testing-library/jest-dom/extend-expect';

describe('Test async', () => {
  it('increments counter after 0.5s', async () => {
    const { getByTestId } = render(<TestAsync />);

    fireEvent.click(getByTestId('button-up'));

    await waitFor(() => {
      const counter = getByTestId('counter');
      expect(counter).toHaveTextContent('1');
    });
  });
});

测试结果:

 PASS  stackoverflow/71639088/index.test.tsx
  Test async
    ✓ increments counter after 0.5s (540 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   88.89 |      100 |      75 |   88.89 |                   
 index.tsx |   88.89 |      100 |      75 |   88.89 | 17                
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.307 s
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React 测试库不更新状态 的相关文章

随机推荐

  • 有关来自 oracle.com 的并发代码的问题,该代码解释了死锁

    我从 oracle com 得到了一段代码 它解释了一般的并发性和特别的死锁 代码来自 https docs oracle com javase tutorial essential concurrency deadlock html ht
  • 如何转换从 json 创建的 `_InternalLinkedHashMap`?

    有时 当在 Dart 中遍历复杂的 json 文件时 如果我们能够告诉编辑器期望的结构是什么 这样我们就可以充分利用编辑器的结构 那就太好了 智能代码补全特征 作为一个玩具示例 请考虑以下脚本作家 dart import dart conv
  • php 中转换为 md5 是错误的

    我有一个表格 其中我从用户那里获取用户名和密码 我正在将密码转换为 md5 然后我将其插入数据库 在用户登录表单中 我获取密码并将其转换为 md5 然后我比较两个密码 它在某些条件下匹配 但如果密码 则失败p w0rd 有什么问题吗 这个问
  • 在 Windows CMD 上递归删除文件或文件夹

    如何从命令行在 Windows 上递归删除文件或文件夹 我找到了这个解决方案 我们在命令行上驱动路径并运行此命令 我给出了一个带有 svn 文件扩展名文件夹的示例 for r R in svn do if exist R rd s q R
  • 安卓短信API

    我知道 SMS 内容提供商不是公共 API 的一部分 至少没有记录 但如果我理解正确 只要您知道如何使用 API 仍然可以使用许多 SMS 功能 例如 将短信插入收件箱非常简单 ContentValues values new Conten
  • 如何使用 jQuery 获取具有相同 z-index 的元素?

    现在 我有不同的元素z index 我想使用 jQuery 将它们分组 div class float div div class float div div class float div 我可以用 attr style 得到z inde
  • 确定我正在使用的实体框架版本?

    我相信有两个版本1和2 版本 2 被称为实体框架 4 0 我如何知道应用程序中正在使用哪个版本 这是在我的 web config 中 这是否意味着我正在使用版本 2
  • TwinCAT 3.0 自动化接口无需 Visual Studio?

    我需要从 C 应用程序启动 关闭 TwinCAT 3 0 正如善意回答的如何从控制台 C 程序启动 关闭TwinCAT系统 https stackoverflow com questions 54077462 how to startup
  • 在 iOS 中将 CSV 上传(转换为电子表格)到 Google Drive?

    我已经生成 csv 文件来存储在本地目录路径中 我尝试将 csv 文件上传到谷歌驱动器 它工作正常 从 Google 云端硬盘打开 csv 文件 但电子表格中未显示预览 所以我想上传 csv 文件 将 csv 转换为电子表格 到谷歌驱动器
  • 扩展 EF DBContext

    我不确定我所问的是否是正确的方法 我有一个数据库优先模型 我想向其中添加某些常用方法 例如更新特定表的特定字段 我知道我可以通过使用适当的方法创建一个类来做到这一点 例如 public static class MyClass public
  • Eclipse 传入同步视图将传入的新文件显示为文件夹

    我希望可以在这里询问 Eclipse 中的奇怪行为 错误 当我将 Eclipse 同步视图与 Subclipse 结合使用时 我可以通过指向左侧的蓝色箭头很好地查看来自其他开发人员的所有传入文件 双击非常适合打开比较编辑器并查看所有更改 一
  • 如何在 C# 中将包含 HTML 的字符串渲染为图像?

    我正在开发一个为用户提供交互式反馈工具的网络应用程序 在此应用程序中 用户可以单击发送反馈按钮 该按钮会在当前网页上覆盖一个覆盖层 并允许他们拖动突出显示区域DIVs 强调某些领域 一旦他们提交反馈 整个页面的 HTML 就会通过 AJAX
  • 当生成正态分布的随机值时,定义范围的最有效方法是什么?

    仅供参考 随机 伪随机 A 当生成均匀随机数时 我可以指定一个范围 即 Math random Math random 10 5 generates numbers between 5 and 15 B 生成一组具有高斯式正态随机性版本的随
  • 从多个 CSV 文件中解析特定列/数据

    所以 最近我一直在使用 D3 js 解析 CSV 文件中的数据 在阅读 Scott Murray 的 交互式数据可视化 一本很棒的书 内容非常丰富 时 它解释了如何从 CSV 中的表中选择所有数据 解析CSV的代码如下所示 d3 text
  • 如何在 JavaScript 中访问 Grails 变量?

    我的 Grails 应用程序中有一个变量BootStrap groovy class BootStrap def init servletContext gt def testGrails 11 我想展示一个 JavaScriptalert
  • 使用 Maven 在 gitlab 中运行 (Docker) 测试容器

    我正在 gitlab ci cd 管道中工作 该管道使用 maven 和 docker 执行其所有命令 不包括部署 在本例中 我尝试运行集成测试 由 Maven 启动 它使用测试容器 用于 mysql 数据库 这些测试在本地运行时工作正常
  • 如何在 Vue 模板中的数组中使数据响应

  • 如何从 Java Web 应用程序将用户发推文到他/她的 Twitter 帐户

    你好 我想构建一个 java web 应用程序 我希望用户从我的 java 应用程序在他的帐户上发推文 现在 当我们考虑 twitter4J 时 它显示的代码正在使用我们自己在 twitter 开发门户上注册的应用程序 它不要求客户提供凭据
  • 使用命名导入在 Je​​st 测试中导入“常量”

    我有一个config and constants我的项目中的文件夹 位于src config test ts src constants index js分别 我已经设置了 Jest 来使用moduleNameMapper如下所示 这样我就
  • React 测试库不更新状态

    我的组件 import React from react const TestAsync gt const counter setCounter React useState 0 const delayCount gt setTimeout