写点什么

React 单元测试实例:快速上手指南

作者 | Sanjeev Sharma

  • 2023-12-20
    北京
  • 本文字数:3121 字

    阅读完需:约 10 分钟

大小:1.42M时长:08:16
React 单元测试实例:快速上手指南

你是否正计划为你的 React 代码编写测试?是否因找不到好的入门教程而感到苦恼?那么,这篇文章正是你所需要的。在本文中,我们将涵盖编写单元测试的所有步骤以及这个过程中可能遇到的错误和问题。

 

本文使用了JestReact Testing Library库。如果你想使用其他库也没关系,文中的一些基础知识也会对你有所帮助。

 

本文涉及的全部代码都托管在 GitHub 上,文末提供了链接地址。

 

为什么要编写测试

当然,不写测试代码也可以完成产品开发。用户、产品经理,甚至测试人员或 QA 都不在乎该产品是否有测试代码。但是你,作为一名开发人员,应该在乎!

 

假设你有一个拥有数万用户的网站,当你对一个公共的工具函数做了一些重构(或添加了一个功能修复),并在应用中某个调用它的地方进行了测试,表明该函数可以正常运行。于是你选择在周五上线(这是个低级错误)。然后,该函数在应用中的其他地方无法运行,导致网站在周末期间出现线上故障。 此时,你多么希望这些地方能有测试代码,可以在发布生产之前自动运行,从而避免此次故障。

 

上述场景比你想象的还要普遍。你可能还没遇到过(不过,这是迟早的事情),但是包括我在内的很多工程师都已经遇到过了。

 

因此,测试代码之所以很重要,主要有以下几个原因:

 

🚀 增强你对代码发布上线的信心。

📜 测试代码本身也是一种文档。

🛠️ 有助于调试和重构。

⌛️ 从长远来看,有助于减少开发时间。

 

对于所有希望晋升的初级开发人员来说,务必要具备编写测试代码的能力。

 

测试教程


我们将从零开始教你编写测试代码,所以请准备好终端。首先,我们使用 vite 创建一个示例项目。

 


在创建项目后,使用以下命令运行它。

 


程序运行之后,你会在页面上看到一个 demo 应用。

 


我们不会给该应用添加新功能,但为了给按钮编写测试代码,我们需要将按钮重构为一个单独的组件。

 


接下来,我们在页面上添加两个按钮:

 

  1. 一个按钮的功能是点击时将 count 的值乘以 2。

  2. 另外一个按钮的功能是点击时按以下顺序执行操作:如果 count 的值以 0 结尾,那么就将它的值除以 2。如果 count 的值是斐波那契数,那么就将它的值加 1。否则,将 count 的值进行平方操作。

 


我们需要在 utils 模块中声明上面代码中用到的两个函数。同时,我们也声明了一些辅助函数,但由于其他地方并不会用到这些辅助函数,因此这里不需要做导出。

 


代码已经准备好,现在可以开始编写测试代码了。这里我们跳过 React 代码,直接先给工具函数编写测试。这有助于我们了解 Jest 框架的大致用法。

 

下面,让我们为 doubleTheNum 函数编写测试。

 


上面的代码用于测试我们的函数是否可以按预期执行。任何测试代码都会包含以下这些关键组件:

 

  1. describe 函数:第一个参数是字符串,它会在测试运行的时候显示。第二个参数则是测试实际执行的函数。describe 函数的主要作用是对同类型的测试进行分组。这里只有一个测试,在另外一个示例中,你会看到其中有多个测试。

  2. it 函数:其参数结构和 describe 函数类似。但这里的字符串参数应该尽可能详细地描述测试函数的具体内容。当然,你也可以使用 test 函数替代 it。

  3. expect 语句块:此函数中的前三行很简单。其最后一行是通过断言来判断 doubleTheNum 函数能否正确运行。此外,这里我们还用到了 toEqual 匹配器函数。

 

Jest 提供了很多匹配器,例如:

 

  1. toBeNull 用于匹配 null。

  2. toBeTruthy 用于匹配判定结果为 true 的语句。

 

想了解关于匹配器的更多信息,参考如下链接:

https://jestjs.io/docs/using-matchers

 

为了运行测试,我们需要先安装 Jest:

 


然后在 package.json 中添加测试脚本:

 


最后,通过执行 yarn test 命令来运行测试。

 

对于大多数人来说,上面的步骤已经足够了。但如果你遇到了与模块导入或 TypeScript 相关的任何问题,请按以下步骤进行操作:

 

  1. 安装并设置 @babel/preset-env:

 


然后,将它配置到 package.josn 中:

 


  1. 安装 TypeScript 依赖库:

 


然后,在 jest.config.ts 中添加 Jest 配置:

 


然后执行测试,结果如下:

 


从输出中可以看到我们在 describe 和 it 函数中声明的字符串信息。

 

🎉 恭喜,你完成了第一个测试!

 

喜欢这篇文章吗?如果觉得还不错,我推荐你看看我的另一篇最受欢迎的文章《Redux完整指南》,阅读量高达 2.5 万:

https://dev.to/thesanjeevsharma/just-redux-the-complete-guide-44d5

 

接下来,我们给 funkyNum 函数编写测试。

 


编写测试时,应该尽量多地覆盖函数的分支和语句。测试覆盖率越高会让人越有信心。

 

如果你再次运行测试,应该会看到以下输出。

 


理想情况下,我们也应该为 isFibonacci 和 isPerfectSquare 函数编写单独的 describe 语句块。在单元测试中,测试代码应该是互相独立的。简洁起见,这里我们没有这样做。

 

💡小提示

 

  1. 通过调用.skip 或 test.skip 来跳过任何测试,或调用 describe.skip 来跳过整个测试块。

 


  1. 通过调用 it.only 或 test.only 执行单个测试。

 


上面我们已经介绍了如何使用 Jest 进行 JS 代码的测试。现在,让我们深入探讨下关于 React 的测试。

 

在开始之前,我们还需要安装一些依赖库:

 


同时,还需要在 jest.config.ts 中添加环境:

 


下面我们给 CounterButton 组件编写一个最基础的测试:

 


在上面的代码中,我们提供了所需的 props ,并尝试渲染组件。对于任何组件,这都应该是你为它编写的第一个测试。因为如果该测试无法通过,那么其他测试就毫无用处。

 

RTL(React Testing Library)的 render 函数将在 document.body 中渲染传入的组件。

 

它还返回了一些诸如 getByText 这样的查询方法,可用于在 DOM 中查找元素。

 

点击这里查阅所有的查询方法。

 

如果你再次运行测试,应该可以看到 2 组测试——全部为绿色且通过。

 


我们编写的第二个测试是测试组件对于 props 的反应。如果各个 prop 之间没有互相依赖,那么应该为每个 prop 参数都编写单独的测试。

 


getByText 函数是一种查询方法,可以让我们通过字符串来获取元素。

 

toBeInTheDocument 函数是一个和 toEqual 类似的匹配器。Jest 默认不提供该函数,需要在安装 @testing-library/jest-dom 库之后才能使用。

 

不同的环境有不同的包,例如在 React Native 环境中,需要使用 @testing-library/jest-native。

 

如果你再次运行测试,测试应该也会通过。

 

最后,我们来编写本文的最后一个测试,同时也是最重要的一个。我们将编写一个测试来检查点击事件处理程序是否按预期工作。

 

为了生成用户事件(例如点击和按键),我们需要安装另外一个包。

 


与之前的测试代码相比,这次的测试代码几乎一样,只有一些微小的差异。

 


注意:由于是模拟用户事件,所以该函数异步执行。

 

第一行的 jest.fn()是一个模拟函数。在测试运行时,可以通过它跟踪诸如调用参数、调用次数等很多非常有用的信息。类似这样的函数,以后你会看到很多。

 

我们还使用了一种新的查询方法 getByRole 来查找按钮元素。

 

在检查模拟函数是否被调用之前,我们需要先等待点击事件完成。

 

就是这样!如果你运行测试,它们应该也会通过。

 


🔗 这里获取所有代码:

https://github.com/thesanjeevsharma/devto-unit-testing

 

下一步


如果你遵循本文成功地完成了测试代码的编写,那么你可以开始在自己的代码库中添加测试代码并且进一步探索各种测试功能了。

 

另外,我建议你进一步了解以下几个方面的内容:

  1. getByTestId——这是一个使用很普遍的查询方法。当其他方法都不好使的时候,可以用它。

  2. 了解Setup和Teardown方法。它将提升你的测试水平。

  3. 学习如何模拟 npm 模块、API 调用、全局状态和上下文等。

 

原文链接:

https://dev.to/thesanjeevsharma/writing-your-first-unit-test-in-react-150h

 

相关阅读:


React JS 广受业界认可,高级开发者年薪百万

从新 React 文档看未来 Web 的开发趋势

我被 React 劫持了,很痛苦又离不开

React 开发者们的 Solid.js 快速入门教程

2023-12-20 10:334869

评论

发布
暂无评论
发现更多内容

5款 Syslog集中系统日志常用工具对比推荐

运维有小邓

Linux syslog IT 运维 linux日志管理

写一个简单的SQL生成工具

不在线第一只蜗牛

数据库 sql

程序员在未来 20 年,会被 ChatGPT 替代吗?

秃头小帅oi

有没有开源的企业网盘,是否适合企业使用?

易成研发中心

【连载 21】性能测试实践——超时结账第一回合

FunTester

Svelte 最新中文文档教程(22)—— Svelte 5 迁移指南

冴羽

前端 前端开发 前端框架 Svelte SvelteKit

比特币再探 8 万关口,是时候为「熊市」做准备了

TechubNews

美股 黄金价格 经济趋势

DAPP(去中心化应用程序)开发全解析:构建去中心化应用的流程

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

白宫加密货币峰会总结:政策信号释放,监管大幅松绑

TechubNews

比特币 比特币减半 加密市场 白宫加密峰会

在华为开发者空间:体验用仓颉基于DeepSeek开发智能聊天机器人

华为云开发者联盟

modelarts CodeArts 仓颉 DeepSeek 华为开发者空间

Java 开发工具合集:从入门到高手必备

飞算JavaAI开发助手

长期主义:为什么说 AI 代码生成是 Java 开发者 2025 必学技能?

飞算JavaAI开发助手

“一天成为 Java 高手” 是噱头?实测 AI 工具如何零基础写出专业级代码!

飞算JavaAI开发助手

Deepseek R1 的技术揭秘与低成本复现,中科院计算所工程师『致 Great』的分享实录已整理!

ModelWhale

人工智能 大语言模型 DeepSeek-R1

交易所开发:数字市场的核心动力

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

解码元翌智能:昇腾AI创新大赛金奖得主的技术拼图

Alter

项目管理软件分类有哪些

易成研发中心

项目管理

看鲲鹏算力生态 | 中国为全球数字化转型提供可复制的东方方案

极客天地

告别加班!AI 生成精准代码,复杂业务逻辑一键搞定

飞算JavaAI开发助手

SD-WAN专线在多分支组网与远程办公网络中的优势

Ogcloud

SD-WAN SD-WAN组网 SD-WAN厂商 sd-wan专线 SD-WAN厂家

SD-WAN厂商选择:Ogcloud SD-WAN解决方案怎么样?

Ogcloud

SD-WAN SD-WAN组网 SD-WAN厂商 sd-wan专线 SD-WAN厂家

【用户投稿】手把手基于Apache SeaTunnel从PostgreSQL同步到Doris

Apache SeaTunnel

项目风险分析报告怎么写

易成研发中心

项目风险

低代码开发模式与传统模式效率对比研究:效率提升97%的案例分析与技术实现

JeeLowCode低代码平台

低代码 低代码平台 低代码, 低代码选择

官宣 | Fluss 0.6 发布公告

Apache Flink

大数据 flink 实时计算 Fluss

警惕!碎片化代码正在拖垮你的项目,完整生成才是王道

飞算JavaAI开发助手

React 单元测试实例:快速上手指南_架构/框架_InfoQ精选文章