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

vue-vben-admin 单元测试实践:基于 Vitest 的测试编写、运行与 CI/CD 集成指南

vue-vben-admin 单元测试实践基于 Vitest 的测试编写、运行与 CI/CD 集成指南【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin本篇技术指南围绕 vue-vben-admin 仓库Vue 3 Vite TypeScript Monorepo 架构的单元测试体系展开讲解该项目如何基于 Vitest 组织测试文件、编写断言用例、一键运行测试并将测试纳入提交前检查与 CI/CD 流程。读完本文你将掌握在 vue-vben-admin及同类 Vite/Monorepo 工程中从零编写、执行、维护单元测试的完整实战方案。Vitest项目的单元测试技术选型vue-vben-admin 采用 Vitest 中有明确说明。Vitest 是构建在 Vite 之上的测试运行器它复用了 Vite 的模块转换与依赖预构建能力因此在 vue-vben-admin 这类本身就基于 Vite 的工程中无需为测试单独搭建一套构建链路测试用例可以直接使用与业务代码相同的import语法、路径别名和 TS 类型解析规则。从根目录 package.json 可以看到vitest作为顶层devDependencies统一管理版本通过 pnpm catalog 机制配合happy-dom轻量 DOM 实现用于在 Node 环境中模拟浏览器 API共同支撑测试运行环境。测试文件组织约定.test.ts后缀与__tests__目录项目内遵循统一的命名约定来放置单元测试文件以.test.ts作为测试文件后缀或将测试文件放入__tests__目录。官方文档给出的约定是测试文件与被测源码放在同一目录。例如如果你创建了utils.ts那么就在同目录下创建对应的utils.test.ts。这种测试与源码同居的方式便于就近维护也是仓库实际采用的主流形态例如 packages/utils/src/helpers/tests/merge-route-modules.test.ts 与 packages/core/base/shared/src/utils/tests/date.test.ts。通过搜索可以发现整个 Monorepo 下分布着80 个左右的.test.ts单元测试文件覆盖了核心包packages/core、packages/effects、packages/stores、packages/utils、内部工具链internal/vite-config、internal/node-utils、应用适配层apps/web-antdv-next以及 playground 示例项目。测试范围覆盖工具函数、请求客户端、表单组件、弹窗/抽屉、状态管理Pinia store、权限控制、vxe-table 插件等核心模块从源码结构看这是仓库质量保障体系中覆盖面相当广的一层。编写第一个单元测试用例编写用例时直接从vitest导入 API 即可。以下是最小可运行示例与文档一致// utils.test.ts import { expect, test } from vitest; import { sum } from ./sum; test(adds 1 2 to equal 3, () { expect(sum(1, 2)).toBe(3); });在真实仓库中测试用例的写法会进一步演进通常使用describe对相关用例分组并配合beforeEach/afterEach做环境准备与清理。以 packages/core/base/shared/src/utils/tests/date.test.ts 为例其结构为import dayjs from dayjs; import { afterEach, beforeEach, describe, expect, it, vi } from vitest; import { formatDate, formatDateTime, getCurrentTimezone, isDate } from ../date; describe(dateUtils, () { beforeEach(() { dayjs.tz.setDefault(); setCurrentTimezone(); // 重置为系统默认 }); afterEach(() { vi.restoreAllMocks(); }); describe(formatDate, () { it(should format a valid ISO date string, () { const formatted formatDate(2024-10-30T12:34:56Z, YYYY/MM/DD); expect(formatted).toMatch(/2024\/10\/30/); }); }); // ... });这段真实用例展示了几个关键实践点beforeEach重置全局状态时区属于易受环境影响的全局状态测试前重置保证用例幂等vi.restoreAllMocks()清理 mock在afterEach中恢复所有被 spy 的函数避免用例间互相污染该用例中还用vi.spyOn(console, error)验证了非法日期会触发错误日志的边界行为边界与异常用例同样重要isDate的测试同时覆盖了合法Date对象与null、字符串等非法输入。运行测试pnpm test:unit全解析在 Monorepo 根目录执行以下命令即可运行全部单元测试pnpm test:unit该命令在根 package.json 中的实际定义为test:unit: vitest run --dom参数含义如下vitest run以**单次执行非 watch**模式运行全部测试适合 CI 场景开发过程中去掉run即直接pnpm vitest可进入 watch 模式保存文件后自动重跑相关用例--dom启用 DOM 环境配合 vitest.config.ts 中的environment: happy-dom配置使组件、DOM 操作类逻辑如use-layout-style、use-scroll-lock等 composables 测试可以正常运行。Vitest 全局配置解读根目录 vitest.config.ts 是仓库测试行为的核心配置import Vue from vitejs/plugin-vue; import VueJsx from vitejs/plugin-vue-jsx; import { configDefaults, defineConfig } from vitest/config; export default defineConfig({ plugins: [Vue(), VueJsx()], test: { environment: happy-dom, environmentOptions: { happyDOM: { settings: { // happy-dom v20 disables JS evaluation by default (security fix). // Treat disabled script loading as success to preserve test behavior. handleDisabledFileLoadingAsSuccess: true, }, }, }, exclude: [ ...configDefaults.exclude, **/e2e/**, **/dist/**, **/.{idea,git,cache,output,temp}/**, **/node_modules/**, **/{stylelint,eslint}.config.*, **/{oxfmt,oxlint}.config.*, ], }, });要点分析plugins: [Vue(), VueJsx()]让测试环境能够编译.vue单文件组件和 TSX这是组件级单元测试如 form-ui、popup-ui 下的用例能够运行的前提happy-dom环境相比 jsdom 更轻量且配置注释揭示了 v20 版本默认禁用脚本执行的安全变更仓库通过handleDisabledFileLoadingAsSuccess: true保持原有测试行为说明该配置是经过真实升级踩坑后的产物exclude在 Vitest 默认排除项基础上额外排除了e2e、dist、各类 IDE 缓存目录以及 lint 相关配置文件——这明确了单元测试与 E2E 测试Playwright在仓库中的职责边界。仓库中的真实单元测试实例以下从仓库中选取几个代表性测试文件说明不同类型模块的测试写法。1. 请求客户端测试Mock Adapter 模式packages/effects/request/src/request-client/request-client.test.ts 使用axios-mock-adapter拦截 HTTP 请求验证RequestClient的 GET/POST/PUT/DELETE、文件上传下载、网络错误与超时、响应拦截器失败等行为it(should successfully make a GET request, async () { mock.onGet(test/url).reply(200, { data: response }); const response await requestClient.get(test/url); expect(response.data).toEqual({ data: response }); }); it(should handle network errors, async () { mock.onGet(/test/error).networkError(); await expect(requestClient.get(/test/error)).rejects.toMatchObject({ isAxiosError: true, message: Network Error, }); });实践启示对外部依赖这里是网络层一律使用 mock 手段隔离测试只关心本模块拦截器、响应解析逻辑的正确性且通过afterEach(() mock.reset())保证用例间互不影响。2. 存储管理器测试Fake Timers 测试过期逻辑packages/core/base/shared/src/cache/tests/storage-manager.test.ts 使用vi.useFakeTimers()配合vi.advanceTimersByTime()来快进时间验证带过期时间的缓存清理逻辑it(should clear expired items, async () { await storageManager.setItem(user, { age: 30, name: John Doe }, 1000); // 1秒过期 vi.advanceTimersByTime(1001); // 快进时间 await storageManager.clearExpiredItems(); const user await storageManager.getItem(user); expect(user).toBeNull(); });实践启示涉及时间、定时器的逻辑不要真的去等待使用 Vitest 的 Fake Timers 精确控制时间流逝让测试既快又稳定。3. 表单、弹窗与状态管理测试仓库中还有大量 UI 与状态层测试例如 packages/core/ui-kit/form-ui/tests/form-api.test.ts表单 API 行为、packages/core/ui-kit/popup-ui/src/modal/tests/modal.test.tsModal 组件交互、packages/stores/src/modules/access.test.ts权限 store等这些用例共同构成了对核心框架代码的行为契约任何破坏性改动都会在pnpm test:unit中立即暴露。现有单元测试状态仓库文档记录了当前单元测试的运行状态截图如下图所示将单元测试纳入提交流程与 CI/CD文档明确建议开发过程中保持单元测试覆盖率并将单元测试作为 CI/CD 的一部分确保部署前测试通过。vue-vben-admin 在这方面的落地可从两处配置得到印证1. 提交前自动检查Lefthook根目录 lefthook.yml 配置了pre-commit钩子在每次提交时串行执行oxlint对暂存文件做类型感知的 lint 并自动修复oxfmt/eslint/stylelint代码格式化与规范检查checkType执行pnpm check:type全量类型检查。虽然当前钩子并未直接触发单元测试考虑提交速度测试通常在 CI 阶段执行但它与测试共同构成了提交前静态检查 CI 动态测试的防线。如果你希望本地提交前就跑测试可参照pnpm test:unit命令自行接入。2. Monorepo 任务编排Turborepo根目录 turbo.json 中声明了test:e2e任务对应根脚本pnpm test:e2e即turbo run test:e2e它与typecheck、build等任务并列表明测试在仓库的标准化任务体系中是一等公民。E2E 测试位于 playground/tests/e2e包含 auth-login.spec.ts登录流程与 layout-system.spec.ts布局系统等用例通过 playground/playwright.config.ts 配置基于 Chromium、自动起 dev server、CI 下 headless 与重试运行。单元测试快、隔离、无浏览器与 E2E 测试慢、真实浏览器、覆盖关键用户路径在此形成了分层互补。项目测试相关的其他脚本根 package.json 中与测试相关的脚本还包括脚本命令用途test:unitvitest run --dom运行全部单元测试单次test:benchmarkvitest bench --run运行 Vitest 性能基准测试test:e2eturbo run test:e2e通过 Turbo 编排运行各包 E2E 测试check:typeturbo run typecheck全仓类型检查常与测试配合使用开发建议与最佳实践小结结合官方文档与仓库源码在 vue-vben-admin 中维护单元测试可遵循以下要点就近存放测试文件与被测文件同目录命名使用.test.ts或放入__tests__保持可运行改动相关模块代码后及时运行pnpm test:unit开发中可用 watch 模式仓库现有 80 个左右的测试文件就是你的回归基线隔离外部依赖网络请求用axios-mock-adapter时间用 Fake Timers全局状态在beforeEach/afterEach中重置与恢复纳入 CI在流水线中执行pnpm test:unit确保测试通过后再进入部署环节这是文档明确建议的质量红线分层配合单元测试覆盖纯逻辑与组件行为关键用户流程交给 playground 下的 Playwright E2E 测试两者在 turbo.json 任务编排下协同工作。【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

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

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