Jest 在测试 React 组件使用 Hooks 中的问题解决方法

React Hooks 是 React 16.8.0 中引入的新特性,它们允许开发者在不编写 class 组件的情况下使用 state 和其他 React 特性。虽然它们让代码变得更加简洁和易于阅读,但同时也给单元测试带来了一些新的挑战。在本文中,我们将探讨如何使用 Jest 测试 React 组件中使用 Hooks 的最佳实践。

基础 Hook 测试

让我们从使用最常见的 Hook - useState - 开始。假设我们有一个组件,它根据用户的输入更新文本:

-------- ----------- -
  ----- ------ -------- - -------------

  -------- ------------------- -
    ----------------------------
  -

  ------ -
    ------ ----------- ------------ ----------------------- --
  --
-

我们可以编写简单的测试来检查它是否正常工作:

------ ----- ---- --------
------ -------- ---------- ---- -------------------------
------ --------- ---- --------------

--------------- ------- ---- -- -------- -- -- -
  ----- ----------- - ----------------- ----
  ----- ----- - ---------------------

  ----------------------- - ------- - ------ ------- ------ - ---

  -------------------------------- --------
---

此处我们使用了 @testing-library/react 库来帮助我们渲染 TextInput 组件。我们获取到组件渲染后返回的一个输入框元素对象 input,然后使用 fireEvent.change 模拟了用户的输入。最后我们使用 expect 断言来验证组件跟随用户输入的变化是否正确。

这种方式是在 hooks 的使用中最常见也是最基础的测试方式,只需简单的模拟用户操作即可,相信大家都已经非常熟悉了。

处理 useEffect 和 useState 联合测试的问题

当一个组件同时使用了 useEffect 和 useState 钩子时,测试可以变得更加棘手。让我们来看一个示例组件:

-------- --------- -
  ----- ------- --------- - ------------

  ------------ -- -
    -------------- - ---- ------- -------- -------
  -- ---------

  -------- ------------- -
    -------------- - ---
  -

  ------ -
    -----
      ------ ------- ------- ---------
      ------- --------------------------- -----------
    ------
  --
-

这个组件有一个单独的状态 - count - 它通过点击按钮来增加。我们还添加了一个 useEffect 钩子,它根据 count 值的变化更新了浏览器的标题。

但是,在编写测试时,我们需要同时跟踪 count 和 useEffect 是否正常工作。我们可以通过下面的测试来确认回调函数是否被触发:

------ ----- ---- --------
------ -------- ---------- ---- -------------------------
------ ------- ---- ------------

------------- ------- -------- ----- -- ------- -- -- -
  --------------- ----
  ----- ------ - ---------------------------------

  ------------------------

  -------------------------------- ------- - --------
---

但是,这个测试并没有使用到 React 的状态。当我们试图仿效此用例使用其他 Hook 时会面临类似的挑战:我们如何知道 count 和 useEffect 是否按预期工作?

我们可以使用 React 的渲染函数 - act() - 来模拟组件内部的状态更新。act() 使我们能够对状态变更进行批量处理来增强渲染性能,也允许我们在更改状态后马上检索该状态的值。实际上,它就像是一个类似于 setTimeout 的 API,可以协调副作用的直观测试。我们可以使用 act() 来改写上面的测试用例,使其测试更准确:

------ ----- ---- --------
------ -------- ---------- ---- ---- -------------------------
------ ------- ---- ------------

------------- ------- -------- ----- -- ------- -- -- -
  --- ------
  --- ---------

  ----------------- --------------------------------- -- -
    ----- ----- - ------------------
    ------- --------- - ------
    ------ ------
  ---

  --------------- ----
  ----- ------ - ---------------------------------

  -------------------------------- ------- - --------

  ------ -- -
    ------------------------
  ---

  -------------------------------- ------- - --------
  ----------------------
  ------------------------------------------
---

在这个版本的测试用例中,我们创建一个 count 变量 - 这是为了使之更容易访问 useState 中的内部 setCount 函数。我们使用 jest.spyOn 来 mock React 的 useState 方法,从而获取到 count 和 setCount 的实时状态。在渲染组件后,我们可以检查页面标题是否已正确更新。然后使用 act() 以函数的形式包装了我们的点击事件,并使用 fireEvent 对按钮进行了点击。最后,我们使用 expect 断言检测 count 的值,并验证 setCount 是否是一个函数。

在测试中 mock 网络请求

在单元测试中,我们希望避免向真实的 API 发送请求,而是用假数据来代替。为了实现这一目标,我们可以使用 Jest 的 mock 功能来 mock 网络请求。

让我们看一个组件,它从 API 获取 GitHub 用户信息并将其渲染到用户界面上:

------ ------ ---------- ---------- ---- --------
------ ----- ---- --------

-------- ----------------------- -
  ----- ------ -------- - ---------------

  ------------ -- -
    ----- -------- --------------- -
      ----- -------- - ----- ------------------------------------------------------
      -----------------------
    -

    ----------------
  -- ------------

  -- ------- -
    ------ ----------------------
  -

  ------ -
    -----
      --------------------
      ---- --------------------- ------------ --
      -----------------
    ------
  --
-

------ ------- ------------

我们可以编写一个测试用例来验证这个组件是否能够正确地渲染出用户信息:

------ ----- ---- --------
------ -------- --------------- ---- -------------------------
------ ----- ---- --------
------ ----------- ---- ----------------

-------------------

----------------- ------- ---- ------ ----- -- -- -
  ----- -------- - -
    ----- -
      ----- ----- -----
      ----------- -------------------------------------------------------
      ---- --------- ----------
    --
  --

  ------------------------------- -- ---------------------------

  ----- ----------- ------------- - ------------------- ------------------- ----
  ----- ---- - ----- ----------------- -- --------------- -------
  ----- ------ - -----------------------
  ----- --- - ------------------- -----------

  ---------------------------------
  -----------------------------------
  --------------------------------
---

在这个示例中,我们使用 Jest 的模拟功能来模拟 axios 的 get 请求,并将其返回的数据替换为我们自己的假数据。在渲染 UserProfile 组件后,我们使用传统的等待方式 - waitForElement - 来等待用户数据呈现。最后,我们可以断言我们的字符串是否在页面上显示。

总结

React Hooks 带来了更加简洁和可读的 React 代码。然而,使用 Hook 后产生的测试问题是实现这个目标的一部分。幸运的是,我们可以通过仔细考虑单元测试的用例和 React 测试 API - 如 act() - 来解决这些问题,并且使用 Jest 的 mock 功能可以使测试更加容易和高效。相信这篇文章可以帮助大家理解并运用好 Jest 测试 React Hooks。

参考链接

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/64735424968c7c53b00cac94


猜你喜欢

  • RxJS 实战:如何防抖动

    引言 在前端开发中,我们经常会遇到一些需要进行防抖操作的情况。例如:输入框搜索,当用户连续输入并删除,我们希望等用户输入停止一定时间后再进行搜索,减轻服务器端的压力,提高用户体验。

    1 年前
  • 如何使用 Netlify 和 Headless CMS 快速搭建下一代 Web 应用程序

    互联网的不断发展,给我们带来日益庞大的数据和信息。网站架构也随之不断变化,由传统的前后端分离模式转变为 Headless 模式。本文将以 Netlify 与 Headless CMS 搭配的方式,给大...

    1 年前
  • 深入剖析 ES9:Promise.prototype.finally()

    深入剖析 ES9:Promise.prototype.finally() 在 ES2018 中,JavaScript 引入了 Promise.prototype.finally() 方法。

    1 年前
  • Flexbox 应用于移动端布局实例

    什么是 Flexbox? Flexbox 是一个用来设计灵活的、可响应的网页布局的工具。它可以方便地设置盒模型及其子元素的大小和位置,以实现自适应和响应式设计。 Flexbox 为前端开发者提供了一种...

    1 年前
  • Express.js中的防盗链技术

    在进行网站开发时,经常需要对图片、音频或其他静态资源进行防盗链,以保护自己的网站资源不被其他网站或第三方应用程序滥用。Express.js提供了几种不同的方法来实现防盗链,本文将介绍其中的一些方法。

    1 年前
  • 如何使用 Chai-Things 测试数组元素的行为

    在前端开发中,我们经常需要对数组进行操作和验证。针对数组元素的行为,我们通常会使用一些测试工具来验证其行为是否符合预期。Chai-Things 是一款可以帮助我们测试数组元素行为的 JavaScrip...

    1 年前
  • 在 Jest 测试框架中使用 mock API

    Jest 是一个非常流行的 JavaScript 测试框架,它具有快速和易用的特点,而且还支持 Mock API,能够帮助开发者更方便地进行单元测试。在本文中,我们将深入探讨 Jest 中的 Mock...

    1 年前
  • 使用 typescript 和 Redux 创建类型安全的应用程序

    使用 TypeScript 和 Redux 创建类型安全的应用程序 随着前端的发展,越来越多的开发者倾向于 TypeScript 和 Redux 来开发应用程序。TypeScript 是一种 Java...

    1 年前
  • 在 Fastify 中使用 Multer 进行文件上传

    在 Web 开发中,文件上传功能是一个非常常见的需求。Multer 是个在 Node.js 中处理 multipart/form-data 类型数据的中间件,使用它可以非常简单地实现文件上传功能。

    1 年前
  • Linux 性能优化必备技能

    在当今互联网时代,Web前端技术已经成为了人们居家生活和工作中不可或缺的一部分。而对于Web前端的开发人员来说,Linux系统是一个非常重要的环境。为了提升性能和优化系统,Web前端开发人员需要掌握一...

    1 年前
  • CSS Grid 如何实现自适应图片缩放

    前言 在现代的网站设计中,图片占据了非常重要的位置。而对于一张图片,使它在所有浏览器、设备上以最佳视觉效果呈现是一个挑战。通常,我们会根据设备的大小,选择不同的图片尺寸来保持页面的美感和响应速度。

    1 年前
  • Node.js 项目开发中的调试技巧

    Node.js 是一种开放源代码的 JavaScript 运行环境,它在 Web 应用程序开发中得到了广泛的应用。然而在实际的项目开发中,难免会遇到各种各样的问题,需要进行调试。

    1 年前
  • TDD+DDD 体系下构建 RESTful API 设计

    在当前互联网时代,RESTful API 的设计已经成为前端开发中非常重要的一部分。然而,要设计出一个符合规范且具有可维护性的 RESTful API 并非易事。本文将介绍如何将 TDD 和 DDD ...

    1 年前
  • PWA 在线升级实战

    前言 越来越多的移动应用和网站开始采用 PWA 技术,使得它们具有了类似于原生应用的体验,例如离线缓存、推送通知等。PWA 技术的一个优势是能够实现在线升级,即用户无需手动下载新版本,而是自动更新到最...

    1 年前
  • Redis 事务操作中的异常处理及预防方案分享

    Redis 是一种高性能的键值存储数据库,并且支持多种数据结构,例如字符串、哈希表、列表、集合和有序集合等。除此之外,Redis 还支持事务的操作,可以保证多个命令的原子性,从而保证了数据的一致性。

    1 年前
  • Webpack 多环境配置指南

    在前端开发中,Webpack 是一款非常流行的构建工具。然而,在实际开发中,我们经常需要针对不同的环境进行不同的构建,例如不同的开发环境、测试环境和生产环境。这时候,Webpack 的多环境配置就变得...

    1 年前
  • 快速掌握 Koa 洋葱模型:一个 BUG 轻松修复

    本文介绍 Koa 洋葱模型的概念和实现,并结合示例代码演示一个常见 bug 的修复方法。 什么是 Koa 洋葱模型? Koa 洋葱模型是指 Koa 框架中间件执行流程的一种模型,也称为“洋葱圈模型”。

    1 年前
  • Custom Elements API: 快速构建自定义标签

    在前端开发中,自定义标签是非常常见的需求。它们可以用来表示特定类型的内容、组合 UI 控件、封装复杂的组件等等。在以往的开发中,我们通常会使用 jQuery 或者其他一些库来实现自定义标签。

    1 年前
  • 解决 Vue.js 项目打包后的文件体积过大

    在使用 Vue.js 开发项目时,我们常常会碰到打包后文件体积过大的问题。文件体积过大不仅会影响页面加载速度,还会带来用户体验上的负面影响。本文将探讨如何解决 Vue.js 项目打包后的文件体积过大的...

    1 年前
  • ES11 中的 BigInt 类型和数字对象:如何简单地做计算

    ES11 引入了一个新的数据类型 BigInt,用于表示大数。在 JavaScript 中,数字的大小最多可以表示到 2^53-1,而 BigInt 可以表示更大的数字,也就是超出了 Number 表...

    1 年前

相关推荐

    暂无文章