拓冰建站拓冰建站
首页 / 资讯中心 / 正文

react-boilerplate 组件测试实战指南:从 Shallow Rendering 到 react-testing-library

react-boilerplate 组件测试实战指南从 Shallow Rendering 到 react-testing-library【免费下载链接】react-boilerplate A highly scalable, offline-first foundation with the best developer experience and a focus on performance and best practices.项目地址: https://gitcode.com/gh_mirrors/rea/react-boilerplate导读本文是 react-boilerplate 官方测试体系中的组件测试篇对应仓库 docs/testing/component-testing.md聚焦 React 视图层Components的两种测试手段React 官方提供的 Shallow Renderer浅渲染与本项目内置集成的 react-testing-library。你将掌握如何隔离组件层级定位缺陷、如何编写快照测试Snapshot Testing锁定组件输出、如何用 mock 函数验证点击等交互行为并学会在 react-boilerplate 的 Jest 工程配置下运行与维护这些测试。测试栈与工程约定在 react-boilerplate 中组件测试并非独立体系而是与 单元测试 共用同一套 Jest 基础设施。根据 docs/testing/README.md 的约定测试文件遵循以下规则将.test.js文件紧挨着被测代码放置放在tests/子目录亦可只要文件以.test.js结尾即可被识别在文件中编写单元测试与组件测试终端执行npm run test运行全部测试。从 jest.config.js 可以看到该识别规则的底层实现testRegex: tests/.*\\.test\\.js$即测试文件必须位于tests/目录下且以.test.js结尾——这正是仓库中每个组件都配有tests/目录例如 app/components/Button/tests/的原因。与组件测试直接相关的工程配置还有setupFilesAfterEnv引入了react-testing-library/cleanup-after-each确保每个用例结束后自动卸载已挂载的 DOM避免用例间相互污染setupFiles: [raf/polyfill]补齐requestAnimationFrame等浏览器 APImoduleNameMapper将.css、图片等静态资源映射到 internals/mocks/cssModule.js 与 internals/mocks/image.js使组件导入样式文件时测试可正常运行项目设置了极高的覆盖率阈值statements 98%、branches 91%、functions 98%、lines 98%组件测试是达标的关键手段。组件测试常用命令定义于 package.jsonnpm run test # 以 NODE_ENVtest 运行 jest --coveragepretest 会先清理 coverage 并执行 lint npm run test:watch # 以 --watchAll 模式监听文件变化持续运行测试Shallow rendering浅渲染单层组件React 官方提供了名为 Shallow Renderer 的渲染器它只渲染组件自身一层不会递归渲染其子组件。这对隔离测试对象、缩小问题定位范围极其有用。以一个简单的Button组件为例对应文档中的示意代码// Button.js import React from react; import CheckmarkIcon from ./CheckmarkIcon; function Button(props) { return ( button classNamebtn onClick{props.onClick} CheckmarkIcon / {React.Children.only(props.children)} /button ); } export default Button;该组件渲染一个button元素内含一个对勾图标组件与一段文本。它属于无状态的 dumb 组件可参考 docs/js/README.md#architecture-components-and-containers 中关于components无状态可复用组件与containers有状态父组件的架构划分。它在父组件中这样被使用// HomePage.js import Button from ./Button; function HomePage() { return Button onClick{this.doSomething}Click me!/Button; }当使用标准ReactDOM.render正常渲染时HTML 输出会递归展开全部层级注释用于对照 JSX 源码与 HTML 结构button !-- Button -- i classfa fa-checkmark/i !-- CheckmarkIcon / -- Click Me! !-- { props.children } -- /button !-- /Button --而使用 Shallow Renderer 渲染时子组件CheckmarkIcon不会被渲染输出只保留Button自身这一层button !-- Button -- CheckmarkIcon / !-- NOT RENDERED! -- Click Me! !-- { props.children } -- /button !-- /Button --对比可见浅渲染的核心价值如果用正常渲染器测试Button一旦CheckmarkIcon内部出错Button的测试也会连带失败难以定位真正的元凶而浅渲染将测试范围严格限定在被测组件自身任何失败都指向本组件的问题。在 react-boilerplate 中浅渲染的用法同样有真实用例佐证。app/containers/App/tests/index.test.js 正是通过react-test-renderer/shallow对容器组件App /做快照测试import React from react; import ShallowRenderer from react-test-renderer/shallow; import App from ../index; const renderer new ShallowRenderer(); describe(App /, () { it(should render and match the snapshot, () { renderer.render(App /); const renderedOutput renderer.getRenderOutput(); expect(renderedOutput).toMatchSnapshot(); }); });需要清醒认识浅渲染的局限所有断言都需手动书写且由于没有真实 DOM无法执行依赖 DOM 的操作如查询节点、模拟浏览器事件。react-testing-library在真实 DOM 中测试为写出更贴近真实使用方式、更易维护的测试react-boilerplate 集成了 react-testing-librarydevDependencies 中锁定版本 6.1.2见 package.json。该库将组件渲染进真实的 DOM 容器并提供查询与事件触发工具。回到Button /组件测试目标有两个一是确认组件连同 children 被正确渲染二是确认点击行为正确。基础测试骨架如下import React from react; import { render, fireEvent } from react-testing-library; import Button from ../Button; describe(Button /, () { it(renders and matches the snapshot, () {}); it(handles clicks, () {}); });Snapshot testing快照锁定渲染输出快照测试的思路是渲染组件后生成一份“快照”与上一次测试成功时提交的快照对比确保组件输出未发生意外变化若快照不存在则首次创建。it(renders and matches the snapshot, () { const text Click me!; const { container } render(Button{text}/Button); expect(container.firstChild).toMatchSnapshot(); });render返回的对象带有container属性即组件被渲染进的容器——默认是一个追加到document.body的div。由于组件渲染在真实 DOM 中可用container.firstChild获取组件根节点作为快照对象。快照文件自动生成于tests目录下的__snapshots__文件夹中务必将这些快照提交进版本库。此后任何人对Button /的输出做出改动测试都会失败并明确提示变更内容从而第一时间发现回归。Behavior testing用 mock 函数验证交互行为测试使用 Jest 的 mock 函数jest.fn()。mock 函数会记录自己是否被调用、调用次数以及调用参数。将其作为onClick处理器传入组件模拟点击后再断言调用情况it(handles clicks, () { const onClickMock jest.fn(); const text Click me!; const { getByText } render(Button onClick{onClickMock}{text}/Button); fireEvent.click(getByText(text)); expect(onClickMock).toHaveBeenCalledTimes(1); });完整测试文件如下原文档此处变量名略有笔误onClickSpy应为onClickMock下文已修正import React from react; import { render, fireEvent } from react-testing-library; import Button from ../Button; describe(Button /, () { it(renders and matches the snapshot, () { const text Click me!; const { container } render(Button{text}/Button); expect(container.firstChild).toMatchSnapshot(); }); it(handles clicks, () { const onClickMock jest.fn(); const text Click me!; const { getByText } render(Button onClick{onClickMock}{text}/Button); fireEvent.click(getByText(text)); expect(onClickMock).toHaveBeenCalledTimes(1); }); });仓库中的真实组件测试范例react-boilerplate 的应用示例刻意展示了 react-testing-library 测试的各种变体其中 app/components/Button/tests/index.test.js 是最佳学习样本。仓库中真实的Button /见 app/components/Button/index.js比文档示例更复杂传入handleRoute时渲染StyledButton否则渲染a链接外层再包裹Wrapper。其测试据此覆盖了多种行为describe(Button /, () { it(should render an a tag if no route is specified, () { const { container } renderComponent({ href }); expect(container.querySelector(a)).not.toBeNull(); }); it(should render a button tag to change route if the handleRoute prop is specified, () { const { container } renderComponent({ handleRoute }); expect(container.querySelector(button)).toBeDefined(); }); it(should handle click events, () { const onClickSpy jest.fn(); const { container } renderComponent({ onClick: onClickSpy }); fireEvent.click(container.querySelector(a)); expect(onClickSpy).toHaveBeenCalled(); }); // ... 还包括 children 数量、class 属性、type 属性透传等断言 });这个范例展示了 react-testing-library 的核心查询思路通过container.querySelector定位真实 DOM 节点再用fireEvent.click触发事件最后以toHaveBeenCalled/toHaveBeenCalledTimes断言 mock 函数行为。仓库中其余组件如 app/components/Footer/tests/index.test.js、app/components/Toggle/tests/index.test.js同样沿用了这套模式并在tests/__snapshots__/下保存了各自的快照文件可作为进一步参考。运行测试与后续进阶编写完测试后在项目根目录执行npm run test # 运行全部测试并生成覆盖率报告coverage/ npm run test:watch # 监听模式下增量运行适合开发期持续验证测试通过后还可将应用部署到真实设备与异地环境做端到端验证详见 docs/testing/remote-testing.md执行npm run start:tunnel借助 ngrok 将本地应用暴露为公网 URL。至此你已经掌握了 react-boilerplate 组件测试的完整闭环浅渲染隔离单层组件、react-testing-library 在真实 DOM 中做快照与行为断言、mock 函数验证交互以及通过__snapshots__提交快照守护组件输出不被意外改动。【免费下载链接】react-boilerplate A highly scalable, offline-first foundation with the best developer experience and a focus on performance and best practices.项目地址: https://gitcode.com/gh_mirrors/rea/react-boilerplate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门