写点什么

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:334565

评论

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

云原生训练营-Week02

jjn0703

云原生训练营

基于STM32+ESP8266+华为云IoT设计的智能门锁

DS小龙哥

2月月更

大数据培训:Flink的提交模式

@零度

大数据 flink

模块八作业

李晓笛

「架构实战营」

【架构实战营】模块八:命题作业

wgl

「架构实战营」

第八周作业

cqyanbo

java培训:Java类加载机制的理解

@零度

JAVA开发 类加载机制

2022年中国智慧医疗行业洞察

易观分析

智慧医疗

架构实战营4期-模块八作业

木几丶

「架构实战营」

模块八作业-设计消息队列存储消息的MySQL表

CH

架构实战营 #架构实战营 「架构实战营」

模块八 - 消息队列存储数据表结构设计

圈圈gor

架构实战营 「架构实战营」

模块八作业

hunk

云原生训练营

2022重磅:增长法则-巧用数字营销 突破企业困局

博文视点Broadview

架构训练营模块八作业

沈益飞

架构训练营 架构师训练营 4 期

模块八作业

黄秀明

「架构实战营」

鉴机识变,面向未来|RocketMQ Summit 2022 即将来袭

阿里巴巴云原生

阿里云 开源 RocketMQ 云原生 开源消息队列

互联网人的命运,就是活到30岁都难?

码农参上

人生 互联网人 打工人

消息队列基于Mysql存储表设计

tony

「架构实战营」

编写 Kubernetes 部署脚本将 httpserver 部署到 Kubernetes 集群

tom

日志管理系统,多种方式总结

架构 日志 slf4j logback

如何写好一个Java类?

蜜糖的代码注释

Java 整洁代码 2月月更

喜报!龙蜥操作系统&龙蜥社区双双荣登2021“科创中国”开源创新榜!

OpenAnolis小助手

开源 操作系统 创新

不能Hook的人生不值得 jsHook和模拟执行

奋飞安全

安全 js hook jshook

分享两个常见的搜索算法:BFS和DFS

华为云开发者联盟

算法 DFS 深度优先搜索 BFS 搜索算法

7大迹象,表明你的DevOps 做对了!

飞算JavaAI开发助手

理论+实践,带你掌握动态规划法

华为云开发者联盟

AI 算法 动态规划法 子问题

郑州轻工业大学——HarmonyOS宠物健康系统的开发分享

HarmonyOS开发者

HarmonyOS 健康检查

架构实战模块八作业

Anlumina

「架构实战营」

Go 语言入门很简单:从 goroutine 出发到并发

宇宙之一粟

Go 语言 goroutine 2月月更

史上最强代码自测方法,没有之一!

万俊峰Kevin

微服务 单元测试 go-zero 测试工具 Go 语言

80 行代码实现简易 RxJS

CRMEB

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