当前位置: 首页 > article >正文

你写的代码没有测试,就像出门不锁门——Jest + Testing Library 从入门到不慌

你改了一行代码手动点了一遍页面觉得没问题就上线了。结果用户反馈“登录按钮点不动了”。你心里咯噔我根本没改登录相关代码啊。今天我们来给你的代码装一把“智能门锁”——单元测试。用 Jest Testing Library把常见 Bug 锁在门外让你改代码时不再心惊胆战。前言很多前端对测试的态度是项目那么赶哪有时间写测试结果修 Bug 的时间比写代码还多。你花 20 分钟写的测试可能帮你省掉 2 小时的通宵排查。测试不是“额外工作”而是安全网。当你需要重构、升级依赖、添加新功能时测试全绿的那一刻比中彩票还安心。今天我们用 Jest测试框架 Testing Library渲染组件、模拟用户操作从零开始给你的 React 项目写第一个测试。不搞复杂概念只写最实用的断言。一、Jest 是啥Testing Library 又是啥JestFacebook 出的测试框架内置断言、模拟函数、覆盖率报告。开箱即用零配置。Testing Library一套帮助你“像用户一样测试”的工具。不测试组件内部 state 或 props只测试用户能看到和能操作的。核心原则测试越接近用户的使用方式越能给你信心。不要测试实现细节比如某个函数被调用了几次、某个 state 变了要测试 UI 上出现了什么、点击后发生了什么变化。二、环境搭建Create React App 用户如果你用 CRAJest 和 Testing Library 已经内置直接写就行。Vite 用户需要手动安装npminstall-Djest testing-library/react testing-library/jest-dom testing-library/user-event vitest# 如果用 VitestVite 推荐配置略不同。这里我们用 Jest 示范配置jest.config.jsmodule.exports{testEnvironment:jsdom,setupFilesAfterEnv:[rootDir/src/setupTests.js],};src/setupTests.jsimporttesting-library/jest-dom;三、第一个测试测试一个纯函数测试最简单的工具函数是入门的绝佳方式。比如utils/formatPrice.jsexportfunctionformatPrice(price,currency¥){return${currency}${price.toFixed(2)};}写测试utils/formatPrice.test.jsimport{formatPrice}from./formatPrice;test(格式化价格带默认货币符号,(){expect(formatPrice(10.5)).toBe(¥10.50);});test(支持自定义货币符号,(){expect(formatPrice(10.5,$)).toBe($10.50);});运行npm test看到绿色通过。这类测试跑得快你应该写很多。四、测试 React 组件渲染与交互假设我们有一个Counter组件import { useState } from react; export function Counter() { const [count, setCount] useState(0); return ( div p计数: {count}/p button onClick{() setCount(count 1)}增加/button /div ); }写测试Counter.test.jsximport { render, screen } from testing-library/react; import userEvent from testing-library/user-event; import { Counter } from ./Counter; test(渲染初始计数为0, () { render(Counter /); const countElement screen.getByText(/计数: 0/i); expect(countElement).toBeInTheDocument(); }); test(点击按钮后计数增加, async () { const user userEvent.setup(); render(Counter /); const button screen.getByRole(button, { name: /增加/i }); await user.click(button); expect(screen.getByText(/计数: 1/i)).toBeInTheDocument(); });注意screen.getByRole比getByText更语义化推荐优先使用。userEvent模拟真实点击会触发 focus、blur 等比fireEvent更接近用户。五、测试异步操作比如数据加载一个显示用户列表的组件从 API 获取数据import { useEffect, useState } from react; export function UserList() { const [users, setUsers] useState([]); useEffect(() { fetch(/api/users) .then(res res.json()) .then(setUsers); }, []); return ( ul {users.map(user li key{user.id}{user.name}/li)} /ul ); }测试时需要 mockfetchimport { render, screen, waitFor } from testing-library/react; import { UserList } from ./UserList; global.fetch jest.fn(() Promise.resolve({ json: () Promise.resolve([{ id: 1, name: 张三 }, { id: 2, name: 李四 }]), }) ); test(加载并显示用户列表, async () { render(UserList /); // 等待数据加载完成 await waitFor(() { expect(screen.getByText(张三)).toBeInTheDocument(); expect(screen.getByText(李四)).toBeInTheDocument(); }); });六、覆盖率别盲目追求 100%运行npm test -- --coverage会生成覆盖率报告。但记住100% 覆盖率不代表没有 Bug。覆盖率低的地方可能是关键逻辑需要补测试但有些样板代码如常量定义、简单 getter不测也罢。重点覆盖业务逻辑和复杂交互。七、测试最佳实践测试行为不测试实现不要测试组件内部 state 的值除非必要而是测试渲染结果。一个测试只断言一件事一个test里可以有多个expect但最好只测一个行为。模拟外部依赖网络请求、localStorage、计时器都要模拟避免测试不稳定。避免测试快照快照测试toMatchSnapshot容易产生大而脆弱的文件改个空格就挂。优先用断言。让测试快速单元测试应该在几秒内跑完如果慢检查是否有真实网络请求或大量渲染。八、持续集成让测试自动跑起来把测试放到 GitHub Actions 里上篇文章的内容。每次 PR 自动跑测试不通过不让合并。这样团队协作时队友的改动不会悄悄破坏你的代码。name:Teston:[push,pull_request]jobs:test:runs-on:ubuntu-lateststeps:-uses:actions/checkoutv4-uses:actions/setup-nodev4with:node-version:18-run:npm ci-run:npm test九、总结测试是给未来的自己写信写测试一开始会慢但能让你后期“闭着眼睛改代码”。Jest Testing Library 是 React 社区标准Vue/Vite 对应 Vitest Testing Library。不要被“测试种类太多”吓到从纯函数和简单组件开始逐步扩大覆盖。下次你改了代码测试全绿你就可以自信地 push。那种感觉比手动点一百遍页面踏实多了。如果你觉得今天的“智能门锁”够踏实点个赞让更多人看到。评论区聊聊你被上线后突然出现的 Bug 坑过吗

相关文章:

你写的代码没有测试,就像出门不锁门——Jest + Testing Library 从入门到不慌

你改了一行代码,手动点了一遍页面,觉得没问题就上线了。结果用户反馈“登录按钮点不动了”。你心里咯噔:我根本没改登录相关代码啊。今天我们来给你的代码装一把“智能门锁”——单元测试。用 Jest Testing Library,把常见 Bug 锁…...

避开BUUCTF《Life on Mars》的思维陷阱:当information_schema查询结果‘不对劲’时,你的排查清单应该有哪些?

破解BUUCTF《Life on Mars》的数据库迷局:当information_schema说谎时的七种侦查策略 在CTF赛场上,SQL注入类题目往往不会按教科书上的剧本发展。当你在BUUCTF《Life on Mars》这道题中执行group_concat(database()) from information_schema.schemata却…...

OSINT自动化框架openeir:模块化设计与情报收集流水线构建

1. 项目概述:一个面向开源情报的现代化工具箱最近在整理自己的技术栈时,发现一个挺有意思的项目,叫heyeir/openeir。乍一看这个名字,可能会有点摸不着头脑,但如果你对开源情报(OSINT)领域有所涉…...

Tera数据库:从入门到精通,打造互联网级分布式存储系统

Tera数据库:从入门到精通,打造互联网级分布式存储系统 【免费下载链接】tera An Internet-Scale Database. 项目地址: https://gitcode.com/gh_mirrors/ter/tera Tera数据库是一个高性能的分布式NoSQL数据库系统,专为处理互联网规模的…...

OpenClaw AI人格守护插件:基于记忆差异分析实现智能体人格稳定

1. 项目概述:一个为AI人格注入“记忆锚点”的守护插件如果你和我一样,长期在AI应用开发的一线,特别是围绕OpenClaw这类框架构建具有“人格”的智能体,那你一定遇到过这个令人头疼的经典问题:AI的人格会“漂移”。今天你…...

SAPO Ink UI组件实战:10个常用交互组件快速上手

SAPO Ink UI组件实战:10个常用交互组件快速上手 【免费下载链接】Ink An HTML5/CSS3 framework used at SAPO for fast and efficient website design and prototyping 项目地址: https://gitcode.com/gh_mirrors/ink2/Ink SAPO Ink是一个由SAPO开发的HTML5/…...

基于Kubernetes Operator的企业级区块链网络自动化部署实践

1. 项目概述:企业级区块链的云原生部署方案如果你正在寻找一个能够将企业级区块链网络快速、稳定地部署到Kubernetes集群上的成熟方案,那么ConsenSys开源的quorum-kubernetes项目绝对值得你花时间深入研究。这个项目不是一个简单的概念验证,而…...

Blender 3MF插件终极指南:从设计到3D打印的完整工作流解决方案

Blender 3MF插件终极指南:从设计到3D打印的完整工作流解决方案 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 你是否曾因3D打印文件格式转换而头疼&#xff…...

基于Node.js的Gemini CLI蓝图:构建高效AI命令行工具

1. 项目概述:一个让Gemini API在命令行中“活”起来的蓝图 如果你和我一样,日常工作中大量时间都泡在终端里,那么你肯定理解那种感觉:为了调用一个AI模型,不得不频繁地在浏览器、API文档和命令行之间来回切换&#xff…...

凌晨还在改论文?这些降重黑科技帮你一键通关

凌晨对着电脑屏幕改论文,那种既疲惫又焦虑的感觉,经历过的人都懂。好在现在的降重工具已经不只是“替换同义词”那么简单了,像 毕业之家 和 PaperRed 这两款主流工具,各自走了完全不同的技术路线,可以根据你的痛点来选…...

别再混淆了!结构方程模型SEM中的反映型vs构成型指标,用PLS-PM一次讲清

结构方程模型中的反映型与构成型指标:理论辨析与PLS-PM实战指南 在数据分析的复杂世界里,结构方程模型(SEM)就像是一把瑞士军刀,能够同时处理测量模型和结构模型。但许多研究者在使用这把"军刀"时,常常忽略了一个关键细…...

一人一书一时代:《凰标》是海棠山铁哥的东方文明宣言@凤凰标志

一人执笔,一书立世,一作定时代。 ——《凰标》题记一、破题:当网文只剩“爽点”,谁来承载文明?行业通病《凰标》回应娱乐至死以笔墨思考时代碎片叙事构建完整文明体系功利写作以文载道,以书传文明 二、个人…...

研究生必备|5款主流文献引用工具深度测评:从课程论文到毕业答辩,哪款能让你省下20小时格式调整时间?

凌晨3点,你盯着Word里200多条参考文献发呆:导师刚通知改用APA格式,而你手动调了一整天的GB/T 7714全得推倒重来。投稿被拒,只因参考文献格式不符合期刊要求。课程论文、小论文、开题报告、毕业大论文……每一次都是格式地狱。本文…...

GPTs 商店深度观察:超级 Agent 的孵化器?

GPTs 商店深度观察:会是下一代超级 AI Agent 的全民孵化器吗? 摘要/引言 2024年6月,OpenAI官方公布了一组数据:GPTs商店上线仅7个月,平台上的自定义GPT数量已经突破1200万,月活使用用户超过8000万,累计为开发者创造的分成收入超过3.2亿美元。这个上线之初被很多业内人士…...

解决Modelsim SE 10.6c仿真Vivado 2019乘法器IP核的“.vhd only”难题(附完整脚本)

解决Modelsim SE 10.6c仿真Vivado 2019乘法器IP核的“.vhd only”难题(附完整脚本) 在FPGA设计流程中,Xilinx Vivado与Mentor Modelsim的组合是许多工程师的首选工具链。但当Vivado 2019生成的乘法器IP核仅提供VHDL接口文件(.vhd)时&#xff…...

Fooocus终极指南:零门槛AI图像生成神器,5分钟从安装到创作

Fooocus终极指南:零门槛AI图像生成神器,5分钟从安装到创作 【免费下载链接】Fooocus Focus on prompting and generating 项目地址: https://gitcode.com/GitHub_Trending/fo/Fooocus 在AI图像生成领域,复杂的技术参数和繁琐的调整过程…...

手把手教你用C语言实现三相锁相环(附完整源码与仿真波形分析)

手把手教你用C语言实现三相锁相环(附完整源码与仿真波形分析) 在电力电子和电机控制领域,锁相环(PLL)技术是实现电网同步、逆变器控制的核心组件。传统教材往往停留在理论推导,而实际工程中,如何…...

用Claude Code+R零代码复现医学顶刊论文:零基础到掌握全流程医学SCI论文训练营

人工智能飞速发展,对于研究生、科研工作者而言,只需要聚焦研究问题创新,统计实操、图表制作、结果呈现等等SCI论文中涉及的工作都有工具可以帮你……我们团队最新开设:“零基础掌握SCI论文全流程:Claude CodeR零代码复…...

(5月最新版)OpenClaw 小龙虾 Windows 一键安装与问题排查

OpenClaw(小龙虾)Windows 11 一键部署教程|2026 新版|零代码・免配置・解压即用 适用系统:Windows 11 专业版 / 家庭版 / 正式版(全版本兼容)当前版本:v2.7.1 下载地址:…...

Tessera:内核级异构GPU分解技术解析与应用

1. Tessera:内核级异构GPU分解技术解析现代GPU数据中心正变得越来越异构化,不同型号的GPU在计算能力、内存带宽和成本效率上存在显著差异。这种异构性源于GPU发布周期与退役时间表的不匹配,以及高昂的成本和有限的供应。例如,Goog…...

基于MCP协议构建企业AI数据安全访问中间件:companyscope-mcp实践

1. 项目概述:一个连接企业与AI的“翻译官”最近在折腾AI应用开发,特别是想用Claude、ChatGPT这些大模型来处理公司内部数据时,遇到了一个普遍痛点:模型能力再强,它也是个“外人”,没法直接访问你公司的数据…...

ARM GICv5 ITS_CR1寄存器配置与中断优化实践

1. ARM GICv5 ITS架构概述中断控制器是现代计算机系统中的关键组件,负责管理和分发硬件中断请求。ARM GICv5架构中的Interrupt Translation Service (ITS)模块通过创新的设备ID和事件ID映射机制,实现了灵活高效的中断路由方案。ITS作为GICv5的可选扩展组…...

AI智能体记忆系统设计:分层架构与向量化检索实战

1. 项目概述:一个为AI智能体设计的记忆系统最近在折腾AI智能体(Agent)相关的项目,发现一个挺有意思的痛点:如何让这些智能体拥有“记忆”?不是那种简单的对话历史记录,而是更接近人类工作记忆和…...

PyTorch分类网络实战:从VGG16、MobileNetV2到ResNet50的架构解析与代码实现

1. 分类网络入门:为什么选择PyTorch? 刚接触深度学习时,我也曾被TensorFlow和PyTorch的选择困扰过。直到第一次用PyTorch实现了一个简单的图像分类器,才真正体会到它的魅力。PyTorch就像乐高积木,用动态计算图的方式让…...

Go语言屏幕自动化工具Rizzler:基于计算机视觉的RPA实践指南

1. 项目概述:一个能“读懂”你屏幕的智能助手最近在折腾一个挺有意思的开源项目,叫ghuntley/rizzler。乍一看这个名字,可能有点摸不着头脑,但如果你对自动化、RPA(机器人流程自动化)或者屏幕交互脚本感兴趣…...

Python自动化反向链接侦察工具:从爬虫原理到SEO实战应用

1. 项目概述:一个反向链接自动化侦察兵如果你做过网站运营、SEO或者内容营销,那你一定对“反向链接”这个词不陌生。简单来说,当网站A上有一个链接指向了你的网站B,这个链接就是你的一个反向链接。在搜索引擎的“世界观”里&#…...

嵌入式系统如何应对VR/AR的技术挑战:从硬件选型到系统优化

1. 虚拟现实与嵌入式系统的交汇点2016年,如果你在嵌入式系统开发圈子里,听到最多的词除了“物联网”,大概就是“虚拟现实”了。那一年,Oculus Rift消费者版正式发货,HTC Vive也刚刚上市,一股VR热潮席卷了科…...

sdd-riper:专业磁盘镜像工具在数据恢复中的原理与实践

1. 项目概述与核心价值最近在整理一些老旧存储设备时,遇到了一个挺典型的问题:手头有几块年代久远的硬盘,里面可能还存着一些早年间的照片、文档,但硬盘本身已经不太稳定,系统里能识别,但拷贝文件时动不动就…...

从工程师漫画竞赛看技术社区运营与内容创作之道

1. 项目概述:一场载入史册的漫画标题竞赛在技术圈子里,工程师们除了埋头画电路、写代码,其实也藏着不少幽默细胞。2011年6月,一场由《EE Times》举办的漫画标题竞赛,就上演了堪称史上最胶着的对决。这场竞赛的核心&…...

功能开关与远程配置:现代Web应用安全发布与动态控制实践

1. 项目概述:从“快乐工具包”到现代应用配置管理 如果你是一名前端或全栈开发者,最近在关注状态管理或应用配置,可能已经听说过 happykit/flags 这个名字。乍一看,它像是一个关于“旗帜”或“开关”的库,但它的核心…...