# 测试指南 **本文引用的文件** - [fms-vue/vitest.config.js](file://fms-vue/vitest.config.js) - [fms-vue/package.json](file://fms-vue/package.json) - [fms-vue/tests/setup.js](file://fms-vue/tests/setup.js) - [fms-vue/tests/helpers/app.js](file://fms-vue/tests/helpers/app.js) - [fms-vue/tests/components/input.spec.js](file://fms-vue/tests/components/input.spec.js) - [fms-vue/tests/services/http.spec.js](file://fms-vue/tests/services/http.spec.js) - [fms-vue/tests/views/login.spec.js](file://fms-vue/tests/views/login.spec.js) - [fms-api/pom.xml](file://fms-api/pom.xml) - [fms-api/src/test/java/cn/g3soft/fmsapi/FmsApiApplicationTests.java](file://fms-api/src/test/java/cn/g3soft/fmsapi/FmsApiApplicationTests.java) - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本指南面向 FMS 项目的测试实践,覆盖前后端测试策略、框架选择、用例编写规范、Mock 策略、覆盖率与报告生成、以及常见场景的示例与最佳实践。前端采用 Vitest + Vue Test Utils + jsdom;后端采用 Spring Boot Test(Jupiter)+ Mockito。文档同时给出端到端(E2E)建议与落地方式,帮助团队在 CI 中稳定运行并持续改进质量。 ## 项目结构 FMS 为前后端分离工程: - 前端 fms-vue:使用 Vite 构建,Vitest 执行单元测试与组件测试,jsdom 提供浏览器环境模拟,Vue Test Utils 挂载/浅渲染组件,Pinia 状态管理,Vue Router 路由。 - 后端 fms-api:Spring Boot 应用,使用 spring-boot-starter-webmvc-test 进行控制器/服务层测试,JUnit Jupiter 作为测试引擎,Mockito 打桩外部依赖。 ```mermaid graph TB subgraph "前端 fms-vue" A["Vitest 配置
vitest.config.js"] B["测试入口与命令
package.json scripts"] C["全局环境初始化
tests/setup.js"] D["测试辅助工具
tests/helpers/app.js"] E["组件/页面/服务测试
tests/*/*.spec.js"] end subgraph "后端 fms-api" F["Maven 依赖与测试启动器
pom.xml"] G["应用上下文测试
FmsApiApplicationTests.java"] H["服务层测试
AuthServiceTests.java"] end A --> E B --> E C --> E D --> E F --> G F --> H ``` 图表来源 - [fms-vue/vitest.config.js:1-34](file://fms-vue/vitest.config.js#L1-L34) - [fms-vue/package.json:1-48](file://fms-vue/package.json#L1-L48) - [fms-vue/tests/setup.js:1-57](file://fms-vue/tests/setup.js#L1-L57) - [fms-vue/tests/helpers/app.js:1-71](file://fms-vue/tests/helpers/app.js#L1-L71) - [fms-api/pom.xml:1-108](file://fms-api/pom.xml#L1-L108) - [fms-api/src/test/java/cn/g3soft/fmsapi/FmsApiApplicationTests.java:1-14](file://fms-api/src/test/java/cn/g3soft/fmsapi/FmsApiApplicationTests.java#L1-L14) - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:1-72](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L1-L72) 章节来源 - [fms-vue/vitest.config.js:1-34](file://fms-vue/vitest.config.js#L1-L34) - [fms-vue/package.json:1-48](file://fms-vue/package.json#L1-L48) - [fms-api/pom.xml:1-108](file://fms-api/pom.xml#L1-L108) ## 核心组件 - 前端测试基础设施 - Vitest 配置:启用 jsdom 环境、全局变量、setupFiles、关闭 CSS、v8 覆盖率与阈值。 - 全局初始化:mock nprogress、polyfill ResizeObserver/IntersectionObserver/matchMedia/scrollTo 等浏览器 API。 - 测试助手:createTestPinia(带 persist)、createTestRouter(memory history)、mountPage(shallowMount + 插件注入)。 - 后端测试基础设施 - Maven 依赖:spring-boot-starter-webmvc-test 提供 @WebMvcTest/@SpringBootTest 能力。 - 应用上下文测试:@SpringBootTest 验证应用可加载。 - 服务层测试:通过 Mockito mock 外部依赖,反射注入被测对象字段,断言业务逻辑。 章节来源 - [fms-vue/vitest.config.js:12-31](file://fms-vue/vitest.config.js#L12-L31) - [fms-vue/tests/setup.js:1-57](file://fms-vue/tests/setup.js#L1-L57) - [fms-vue/tests/helpers/app.js:17-71](file://fms-vue/tests/helpers/app.js#L17-L71) - [fms-api/pom.xml:86-96](file://fms-api/pom.xml#L86-L96) - [fms-api/src/test/java/cn/g3soft/fmsapi/FmsApiApplicationTests.java:1-14](file://fms-api/src/test/java/cn/g3soft/fmsapi/FmsApiApplicationTests.java#L1-L14) - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:18-42](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L18-L42) ## 架构总览 前后端测试分层与协作关系如下: - 前端 - 单元/组件测试:Vitest + jsdom + Vue Test Utils,聚焦组件行为、事件、状态变化。 - 服务层测试:mock 统一请求模块,验证拦截器与错误处理。 - 页面集成测试:mountPage 装配 Pinia/Router,验证路由跳转与会话写入。 - 后端 - 单元测试:Mockito 隔离数据库/JWT 等外部依赖,验证服务方法。 - 集成测试:@SpringBootTest 启动容器,验证装配与上下文。 - Web 层测试:基于 webmvc-test 的控制器断言(可按需扩展)。 ```mermaid sequenceDiagram participant Dev as "开发者" participant FE as "前端测试(Vitest)" participant BE as "后端测试(Spring Boot)" participant DB as "数据库(可选)" participant Ext as "外部依赖(Mock)" Dev->>FE : 运行 pnpm test / test : coverage FE->>FE : setup.js 初始化环境 FE->>FE : helpers/app.js 装配 Pinia/Router FE->>Ext : vi.mock 请求/消息等 FE-->>Dev : 组件/页面/服务用例结果 Dev->>BE : 运行 mvn test BE->>BE : @SpringBootTest 启动上下文 BE->>Ext : Mockito 打桩 DbUtils/JwtUtils BE-->>DB : 按需连接(或跳过) BE-->>Dev : 服务/控制器用例结果 ``` 图表来源 - [fms-vue/tests/setup.js:1-57](file://fms-vue/tests/setup.js#L1-L57) - [fms-vue/tests/helpers/app.js:17-71](file://fms-vue/tests/helpers/app.js#L17-L71) - [fms-api/pom.xml:86-96](file://fms-api/pom.xml#L86-L96) - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:18-42](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L18-L42) ## 详细组件分析 ### 前端测试环境与工具链 - 环境初始化 - 全局 polyfill:ResizeObserver、IntersectionObserver、matchMedia、Element.scrollTo/scrollIntoView,避免 jsdom 缺失导致的异常。 - 第三方库 Mock:nprogress 的全局方法被替换为空实现,避免 DOM 副作用。 - 测试助手 - createTestPinia:创建带 persist 插件的 Pinia 实例并安装,保证 store 行为与生产一致。 - createTestRouter:内存历史路由,支持初始 location。 - mountPage:浅渲染组件,自动注入 Pinia/Router,便于页面级测试。 ```mermaid flowchart TD Start(["测试启动"]) --> Setup["执行 tests/setup.js"] Setup --> Polyfills["注入浏览器 API polyfill"] Polyfills --> Helpers["导入 helpers/app.js"] Helpers --> Pinia["createTestPinia() 安装 persist"] Pinia --> Router["createTestRouter(memory history)"] Router --> Mount["mountPage(shallowMount)"] Mount --> RunSpecs["执行 *.spec.js 用例"] ``` 图表来源 - [fms-vue/tests/setup.js:1-57](file://fms-vue/tests/setup.js#L1-L57) - [fms-vue/tests/helpers/app.js:17-71](file://fms-vue/tests/helpers/app.js#L17-L71) 章节来源 - [fms-vue/tests/setup.js:1-57](file://fms-vue/tests/setup.js#L1-L57) - [fms-vue/tests/helpers/app.js:17-71](file://fms-vue/tests/helpers/app.js#L17-L71) ### 组件测试示例:输入框 Input - 目标:验证默认/密码/数字/文本域模式下的渲染、事件转发、状态切换、边界行为。 - 要点: - 使用 data-slot/aria-label 定位元素,不依赖样式类名。 - 异步更新使用 nextTick/flushPromises,避免固定延时。 - 对复杂交互(拖拽调整高度)使用原生事件触发并断言最终状态。 ```mermaid sequenceDiagram participant T as "测试用例" participant M as "Input 组件" participant I as "原生 input/textarea" T->>M : mount(Input, props) T->>I : setValue('...') I-->>M : 触发 update : modelValue/change M-->>T : 断言事件/属性/类名 ``` 图表来源 - [fms-vue/tests/components/input.spec.js:1-412](file://fms-vue/tests/components/input.spec.js#L1-L412) 章节来源 - [fms-vue/tests/components/input.spec.js:1-412](file://fms-vue/tests/components/input.spec.js#L1-L412) ### 页面集成测试示例:登录页 - 目标:验证登录流程中的会话写入、路由跳转、持久化存储清理。 - 要点: - 使用 mountPage 装配 Pinia/Router,mock 统一 API 层。 - beforeEach 清理 localStorage/sessionStorage,防止跨用例污染。 - 使用 flushPromises + nextTick 等待异步完成。 ```mermaid sequenceDiagram participant U as "用户操作" participant P as "登录页组件" participant S as "auth store" participant R as "router" U->>P : 提交表单 P->>S : setSession(token,user,org) S-->>P : 状态更新(isAuthenticated=true) P->>R : push(redirect) R-->>U : 跳转到目标页 ``` 图表来源 - [fms-vue/tests/views/login.spec.js](file://fms-vue/tests/views/login.spec.js) - [fms-vue/tests/helpers/app.js:45-71](file://fms-vue/tests/helpers/app.js#L45-L71) 章节来源 - [fms-vue/tests/views/login.spec.js](file://fms-vue/tests/views/login.spec.js) - [fms-vue/tests/helpers/app.js:45-71](file://fms-vue/tests/helpers/app.js#L45-L71) ### 服务层测试示例:HTTP 拦截器 - 目标:验证请求头注入 Authorization、响应码处理(成功/401/业务错误/网络异常)。 - 要点: - 仅 mock 统一请求模块,确保确定性驱动。 - 断言是否注入 token、跳转路径、抛错信息。 ```mermaid flowchart TD Req["发起请求"] --> CheckToken{"存在 token?"} CheckToken --> |是| AddAuth["注入 Authorization"] CheckToken --> |否| SkipAuth["不注入"] AddAuth --> Send["发送请求"] SkipAuth --> Send Send --> Resp{"响应 code"} Resp --> |0| Success["返回成功数据"] Resp --> |401| ClearLogin["清会话并跳转 /login?reason=expired"] Resp --> |40101| ClearReplace["清会话并跳转 /login?reason=session-replaced"] Resp --> |其他| ThrowErr["抛出业务错误"] ``` 图表来源 - [fms-vue/tests/services/http.spec.js](file://fms-vue/tests/services/http.spec.js) 章节来源 - [fms-vue/tests/services/http.spec.js](file://fms-vue/tests/services/http.spec.js) ### 后端服务层测试示例:认证服务 - 目标:验证登录逻辑,包括隐藏超级管理员空密码登录、JWT 生成、用户信息组装。 - 要点: - 使用 Mockito mock DbUtils/JwtUtils,反射注入到被测对象。 - 断言返回值包含 token、user 字段正确性。 ```mermaid sequenceDiagram participant T as "测试用例" participant A as "AuthService" participant DB as "DbUtils(Mock)" participant JWT as "JwtUtils(Mock)" T->>A : login(org, account, password, ...) A->>DB : loadUserForAuthentication(...) DB-->>A : 用户数据 A->>JWT : generateToken(account, org, secret) JWT-->>A : token A-->>T : Optional {token, user} ``` 图表来源 - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:18-72](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L18-L72) 章节来源 - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:18-72](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L18-L72) ### 端到端(E2E)测试建议 - 技术选型:Playwright(推荐)或 Cypress。Playwright 在多浏览器、并行、录制调试方面优势明显。 - 场景建议: - 登录 -> 进入仪表盘 -> 打开模块管理 -> 新增/编辑/删除 -> 退出登录。 - 权限控制:不同角色访问受限页面应重定向或提示。 - 与现有脚本:仓库中存在 .playwright-cli 目录,可作为参考脚本组织方式。 [本节为概念性说明,不直接分析具体源码文件] ## 依赖关系分析 - 前端 - Vitest 依赖 jsdom 提供 DOM 环境;Vue Test Utils 用于组件挂载;Pinia 与 Router 通过 helpers 注入。 - 覆盖率由 @vitest/coverage-v8 提供,输出 text/html 报告。 - 后端 - spring-boot-starter-webmvc-test 提供测试能力;JUnit Jupiter 为测试引擎;Mockito 用于依赖打桩。 ```mermaid graph LR V["Vitest"] --> JSDOM["jsdom"] V --> VTU["@vue/test-utils"] VTU --> PINIA["Pinia"] VTU --> ROUTER["Vue Router"] V --> COV["@vitest/coverage-v8"] SB["Spring Boot Test"] --> JUnit["JUnit Jupiter"] SB --> Mockito["Mockito"] ``` 图表来源 - [fms-vue/vitest.config.js:17-31](file://fms-vue/vitest.config.js#L17-L31) - [fms-vue/package.json:35-46](file://fms-vue/package.json#L35-L46) - [fms-api/pom.xml:86-96](file://fms-api/pom.xml#L86-L96) 章节来源 - [fms-vue/vitest.config.js:17-31](file://fms-vue/vitest.config.js#L17-L31) - [fms-vue/package.json:35-46](file://fms-vue/package.json#L35-L46) - [fms-api/pom.xml:86-96](file://fms-api/pom.xml#L86-L96) ## 性能考虑 - 前端 - 使用 shallowMount 减少子组件渲染开销,仅在需要时 mount。 - 避免真实网络请求,集中 mock 统一 API 层。 - 合理使用 nextTick/flushPromises,避免 setTimeout 猜测时序。 - 后端 - 单元测试尽量无数据库依赖,使用 Mockito 隔离外部系统。 - 集成测试按需启用数据库,必要时使用内存库或测试专用配置。 - 控制测试数据规模,避免大数据量导致用例缓慢。 [本节为通用指导,不直接分析具体源码文件] ## 故障排查指南 - 前端常见问题 - jsdom 未实现的 API 报错:检查 tests/setup.js 是否已 polyfill。 - Pinia persist 不生效:确保使用 createTestPinia,而非直接 setActivePinia(createPinia())。 - 跨用例状态泄漏:beforeEach 清理 localStorage/sessionStorage。 - 异步断言失败:使用 flushPromises + nextTick,避免固定延时。 - 后端常见问题 - 上下文加载失败:检查 @SpringBootTest 配置与依赖注入。 - 外部依赖未 mock:确认 DbUtils/JwtUtils 等已被 mock 并设置期望。 - 反射注入失败:确保字段名与类型匹配。 章节来源 - [fms-vue/tests/setup.js:1-57](file://fms-vue/tests/setup.js#L1-L57) - [fms-vue/tests/helpers/app.js:17-31](file://fms-vue/tests/helpers/app.js#L17-L31) - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:18-42](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L18-L42) ## 结论 本项目已形成清晰的前后端测试体系:前端以 Vitest 为核心,配合 jsdom 与 Vue Test Utils,建立稳定的组件/页面/服务层测试;后端以 Spring Boot Test 为基础,结合 JUnit 与 Mockito,保障服务逻辑正确性。通过统一的覆盖率门槛与报告机制,可在 CI 中持续把控质量。建议逐步补齐关键路径的 E2E 测试,进一步提升交付信心。 [本节为总结性内容,不直接分析具体源码文件] ## 附录 ### 测试命令速查 - 前端 - 全部测试:pnpm test - 单文件测试:pnpm test:file tests/views/login.spec.js - 覆盖率:pnpm test:coverage - 监听模式:pnpm test:watch - 后端 - 全部测试:mvn test - 指定类:mvn test -Dtest=FmsApiApplicationTests - 指定包:mvn test -Dtest="cn.g3soft.fmsapi.service.*" 章节来源 - [fms-vue/package.json:6-20](file://fms-vue/package.json#L6-L20) ### 覆盖率要求与报告 - 前端 - 覆盖率提供者:v8 - 报告格式:text、html - 统计范围:src/**/*.{js,vue} - 排除项:src/main.js、src/theme/presets.js - 阈值:lines/functions/branches/statements ≥ 60% - 后端 - 可使用 JaCoCo 集成(如需),在 pom.xml 中配置 maven-surefire-plugin 与 jacoco-maven-plugin 生成报告。 章节来源 - [fms-vue/vitest.config.js:17-31](file://fms-vue/vitest.config.js#L17-L31) ### 测试数据管理 - 前端 - 使用本地 fixture 或工厂函数构造最小可用数据。 - 通过 vi.mock 统一返回确定性的 API 响应。 - 每次测试前清理持久化存储,避免污染。 - 后端 - 使用静态数据或工厂方法构造入参。 - 对外部依赖(数据库/JWT)使用 Mockito 返回预设值。 - 集成测试建议使用独立测试库或内存库,避免影响生产数据。 [本节为通用指导,不直接分析具体源码文件] ### 常见场景示例指引 - 组件测试:见 tests/components/input.spec.js,覆盖多模式、事件、边界。 - 页面集成测试:见 tests/views/login.spec.js,验证登录流程与路由跳转。 - 服务层测试:见 tests/services/http.spec.js,验证拦截器与错误处理。 - 后端服务测试:见 service/AuthServiceTests.java,验证登录逻辑与 JWT 生成。 章节来源 - [fms-vue/tests/components/input.spec.js:1-412](file://fms-vue/tests/components/input.spec.js#L1-L412) - [fms-vue/tests/views/login.spec.js](file://fms-vue/tests/views/login.spec.js) - [fms-vue/tests/services/http.spec.js](file://fms-vue/tests/services/http.spec.js) - [fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java:18-72](file://fms-api/src/test/java/cn/g3soft/fmsapi/service/AuthServiceTests.java#L18-L72)