# 测试指南
**本文引用的文件**
- [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