【ArchSummit架构师峰会】基于大模型的基础框架、中台、应用层等专题全覆盖 >>> 了解详情
写点什么

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

评论

发布
暂无评论

还重构?就你那代码只能铲了重写!

小傅哥

Java 小傅哥 代码优化 代码重构 开发标准

图计算的应用

6979阿强

一期投资30亿!“中国—东盟星动云算力中心项目”将落地广西巴马

旺链科技

数字经济 产业区块链 一带一路

作业八:设计消息队列存储消息数据的 MySQL 表格

燕燕 yen yen

#架构实战营

乘着汽车智能化的浪潮,“汽车人”的职业方向选择(二)

SOA开发者

程序员 软件 汽车 职业发展

闲鱼消息发展回顾

OpenIM

没想到专科的我也能拿到年薪30W的offer,仅凭阿里这份JDK源码笔记

Java架构师迁哥

在外包做开发3年,为了进大厂,耗时半年,整合出25W字Java全栈面试题,这就是我的决心

Java架构师迁哥

手撸二叉树之翻转二叉树

HelloWorld杰少

9月日更

DBA:介里有你没有用过的“CHUAN”新社区版本Redis6.0

华为云开发者联盟

redis 开源 多线程 Redis 6.0 华为云DCS

来自阿里巴巴佛系Java程序员的指南,惊喜

Java 程序员 后端

Apache ShenYu源码阅读系列-基于WebSocket的数据同步

子夜2104

Java 开源 网关 shenyu

译介:《电动滑板车的崛起》

姬翔

Python——绑定与方法调用

在即

9月日更

【Vuex 源码学习】第三篇 - Vuex 中 State 状态的实现

Brave

源码 vuex 9月日更

通过线路输入功能快速创建吉他谱

懒得勤快

玩转anyRTC用户控制台

anyRTC开发者

音视频 WebRTC 语音通话 视频通话 用户后台

普通二本的辛酸Java面试之路,Java程序员架构之路该如何继续学习

Java 程序员 后端

某大厂开发者对于Java多线程的总结,Java排序算法面试

Java 程序员 后端

“人类高质量数据”如何训练计算机视觉模型?

澳鹏Appen

计算机视觉

【预告】网络研讨会|下一代汽车操作系统微内核seL4:seL4基金会主席谈物理系统安全工程实践

鉴释

自动驾驶 操作系统 微内核

每个程序员都必须掌握的8种数据结构,2021Java开发面试解答

Java 程序员 后端

60w“跳”进腾讯!你知道我经历了什么吗?

Java架构师迁哥

图遍历算法

6979阿强

图遍历 GraphScope

从 0 到 1 开发一个聊天通讯 服务 复盘总结分享

程序员海军

Vue 大前端 websocket 实时通讯 引航计划

Android音频API

轻口味

android 音视频 引航计划 9月日更

普通二本的辛酸Java面试之路,34岁Java程序员裸辞

Java 程序员 后端

每个程序员都必须掌握的8种数据结构,springmvc源码流程总结

Java 程序员 后端

GaussDB(for MySQL)如何快速创建索引?华为云数据库资深架构师为您揭秘

华为云开发者联盟

数据库 算法 索引 GaussDB(for MySQL) MySQL索引

我用MRS-ClickHouse构建的用户画像系统,让老板拍手称赞

华为云开发者联盟

数据库 标签 用户画像 MRS ClickHouse 列式存储

来一份全面的面试宝典练练手,6年老Java面经总结

Java 程序员 后端

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