380 lines
8.3 KiB
Markdown
380 lines
8.3 KiB
Markdown
# 🧪 camelCase API 测试指南
|
||
|
||
## 测试目标
|
||
|
||
验证整条链路:**后端 Go → JSON (camelCase) → 前端 TypeScript** 是否正常工作。
|
||
|
||
## 📋 准备工作
|
||
|
||
### 1. 确保依赖已安装
|
||
|
||
```bash
|
||
# 后端依赖
|
||
cd backend
|
||
go mod download
|
||
|
||
# 前端依赖
|
||
cd ../frontend
|
||
npm install
|
||
```
|
||
|
||
### 2. 确保代码已重新生成
|
||
|
||
```bash
|
||
# 从项目根目录
|
||
make openapi-gen-frontend
|
||
```
|
||
|
||
## 🎮 后端运行模式
|
||
|
||
后端提供三种运行模式,根据你的需求选择:
|
||
|
||
### run-0: Mock 模式(推荐用于测试)
|
||
```bash
|
||
cd backend
|
||
make run-0
|
||
```
|
||
- ✅ **无依赖**:不需要数据库、Redis 等
|
||
- ✅ **快速启动**:立即可用
|
||
- ✅ **热重载**:代码变更自动重启
|
||
- ✅ **适合开发和测试**
|
||
|
||
### run-1: 真实数据库模式
|
||
```bash
|
||
cd backend
|
||
make run-1
|
||
```
|
||
- 🐘 PostgreSQL (Docker)
|
||
- 🔥 热重载
|
||
- 📊 真实数据持久化
|
||
- 停止:`Ctrl+C` + `make clean-1`
|
||
|
||
### run-2: 全容器模式
|
||
```bash
|
||
cd backend
|
||
make run-2
|
||
```
|
||
- 🐳 所有服务在 Docker 中
|
||
- 🔄 后台运行
|
||
- 🏭 接近生产环境
|
||
- 停止:`docker compose down`
|
||
|
||
## 🚀 测试步骤
|
||
|
||
### 方案 A:自动化测试脚本(推荐)
|
||
|
||
#### 步骤 1: 启动后端服务(Mock 模式)
|
||
|
||
```bash
|
||
# 在终端 1 中运行
|
||
cd /home/mango/workspace/ocdp-go/backend
|
||
make run-0
|
||
|
||
# run-0: Mock 模式(无依赖,最简单)
|
||
# run-1: 真实 PostgreSQL(Docker)
|
||
# run-2: 全部 Docker(后台运行)
|
||
```
|
||
|
||
等待看到:
|
||
```
|
||
🎭 Run-0: Hot reload + Mock
|
||
✓ Server started on :8080 (Mock mode)
|
||
```
|
||
|
||
#### 步骤 2: 运行 API 测试脚本
|
||
|
||
```bash
|
||
# 在终端 2 中运行
|
||
cd /home/mango/workspace/ocdp-go
|
||
./scripts/test-api-camelcase.sh
|
||
```
|
||
|
||
**预期结果:**
|
||
- ✅ 所有 API 返回 camelCase 字段
|
||
- ✅ `accessToken`, `refreshToken`, `userId` 存在
|
||
- ✅ `createdAt`, `updatedAt` 存在
|
||
- ✅ `caData`, `certData`, `keyData`, `hasCaData` 存在
|
||
|
||
#### 步骤 3: 启动前端服务
|
||
|
||
```bash
|
||
# 在终端 3 中运行
|
||
cd /home/mango/workspace/ocdp-go/frontend
|
||
npm run dev
|
||
```
|
||
|
||
访问: http://localhost:5173
|
||
|
||
#### 步骤 4: 前端测试页面
|
||
|
||
访问: **http://localhost:5173/api-test**
|
||
|
||
点击 **"🚀 完整测试"** 按钮,观察:
|
||
|
||
1. **注册测试** - 创建新用户
|
||
2. **登录测试** - 获取 JWT token
|
||
- 验证响应包含 `accessToken` (camelCase)
|
||
3. **获取集群列表** - 测试 GET 请求
|
||
- 验证响应包含 `createdAt`, `updatedAt` (camelCase)
|
||
4. **创建集群** - 测试 POST 请求
|
||
- 发送 `caData`, `certData`, `keyData` (camelCase)
|
||
- 验证响应包含 `hasCaData` (camelCase)
|
||
|
||
**预期结果:**
|
||
```
|
||
🧪 开始完整测试流程...
|
||
|
||
步骤 1: 注册用户
|
||
✅ 注册成功
|
||
|
||
步骤 2: 登录
|
||
✅ 登录成功 - Token: eyJhbGciOiJIUzI1NiIs...
|
||
|
||
步骤 3: 获取集群列表
|
||
✅ 获取成功 - 共 X 个集群
|
||
|
||
步骤 4: 创建测试集群 (camelCase)
|
||
✅ 创建成功 - ID: cluster-xxx
|
||
|
||
🎉 完整测试流程完成! 所有 API 调用成功,camelCase 工作正常!
|
||
```
|
||
|
||
### 方案 B:手动 cURL 测试
|
||
|
||
#### 1. 测试健康检查
|
||
|
||
```bash
|
||
curl http://localhost:8080/health
|
||
# 预期: {"status":"healthy"}
|
||
```
|
||
|
||
#### 2. 测试登录(获取 Token)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"username": "admin",
|
||
"password": "admin123"
|
||
}'
|
||
```
|
||
|
||
**预期响应(注意 camelCase):**
|
||
```json
|
||
{
|
||
"accessToken": "eyJhbGci...",
|
||
"refreshToken": "eyJhbGci...",
|
||
"userId": "user-123",
|
||
"username": "admin"
|
||
}
|
||
```
|
||
|
||
✅ **验证点**:字段名是 `accessToken`、`refreshToken`、`userId`(camelCase)
|
||
|
||
#### 3. 测试创建集群(使用 camelCase)
|
||
|
||
```bash
|
||
# 替换 YOUR_TOKEN 为上一步获取的 token
|
||
curl -X POST http://localhost:8080/api/v1/clusters \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||
-d '{
|
||
"name": "test-cluster",
|
||
"host": "https://k8s.example.com:6443",
|
||
"description": "Test cluster",
|
||
"caData": "LS0tLS1CRUdJTi1DRVJUSUZJQ0FURS0tLS0t",
|
||
"certData": "LS0tLS1CRUdJTi1DRVJUSUZJQ0FURS0tLS0t",
|
||
"keyData": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVkt"
|
||
}'
|
||
```
|
||
|
||
**预期响应(注意 camelCase):**
|
||
```json
|
||
{
|
||
"id": "cluster-abc123",
|
||
"name": "test-cluster",
|
||
"host": "https://k8s.example.com:6443",
|
||
"description": "Test cluster",
|
||
"hasCaData": true,
|
||
"hasCertData": true,
|
||
"hasKeyData": true,
|
||
"hasToken": false,
|
||
"caData": "••••••••",
|
||
"certData": "••••••••",
|
||
"keyData": "••••••••",
|
||
"createdAt": "2025-11-10T10:00:00Z",
|
||
"updatedAt": "2025-11-10T10:00:00Z"
|
||
}
|
||
```
|
||
|
||
✅ **验证点**:
|
||
- 请求使用 `caData`、`certData`、`keyData` (camelCase)
|
||
- 响应包含 `hasCaData`、`createdAt`、`updatedAt` (camelCase)
|
||
|
||
#### 4. 测试获取集群列表
|
||
|
||
```bash
|
||
curl -X GET http://localhost:8080/api/v1/clusters \
|
||
-H "Authorization: Bearer YOUR_TOKEN"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
[
|
||
{
|
||
"id": "cluster-abc123",
|
||
"name": "test-cluster",
|
||
"createdAt": "2025-11-10T10:00:00Z",
|
||
"updatedAt": "2025-11-10T10:00:00Z",
|
||
...
|
||
}
|
||
]
|
||
```
|
||
|
||
✅ **验证点**:响应字段使用 camelCase
|
||
|
||
## 🔍 验证清单
|
||
|
||
### 后端验证
|
||
|
||
- [ ] Go struct JSON tags 使用 camelCase
|
||
- [ ] OpenAPI 规范属性使用 camelCase
|
||
- [ ] API 响应 JSON 使用 camelCase
|
||
- [ ] 后端可以正确解析 camelCase 请求
|
||
|
||
### 前端验证
|
||
|
||
- [ ] TypeScript 类型定义使用 camelCase
|
||
- [ ] 前端代码使用 camelCase 属性
|
||
- [ ] API 调用发送 camelCase JSON
|
||
- [ ] 响应解析为 camelCase 对象
|
||
- [ ] IDE 自动补全正常工作
|
||
|
||
### 字段验证
|
||
|
||
必须验证这些关键字段都是 camelCase:
|
||
|
||
**Auth API:**
|
||
- `accessToken` ✅
|
||
- `refreshToken` ✅
|
||
- `userId` ✅
|
||
|
||
**Cluster API:**
|
||
- `caData` ✅
|
||
- `certData` ✅
|
||
- `keyData` ✅
|
||
- `hasCaData` ✅
|
||
- `hasCertData` ✅
|
||
- `hasKeyData` ✅
|
||
- `hasToken` ✅
|
||
- `createdAt` ✅
|
||
- `updatedAt` ✅
|
||
|
||
**Registry API:**
|
||
- `registryId` ✅
|
||
- `registryUrl` ✅
|
||
- `hasPassword` ✅
|
||
- `createdAt` ✅
|
||
- `updatedAt` ✅
|
||
|
||
**Instance API:**
|
||
- `registryId` ✅
|
||
- `clusterId` ✅
|
||
- `valuesYaml` ✅
|
||
|
||
## 📊 测试结果示例
|
||
|
||
### 成功的测试输出
|
||
|
||
```
|
||
🧪 OCDP API camelCase 测试
|
||
================================
|
||
|
||
步骤 1: 检查服务健康状态
|
||
✅ 后端服务运行正常
|
||
|
||
步骤 2: 测试注册 API
|
||
✅ 注册成功,发现 accessToken 字段 (camelCase)
|
||
|
||
步骤 3: 测试登录 API
|
||
✅ 登录成功!
|
||
Token (前20字符): eyJhbGciOiJIUzI1NiIs...
|
||
✅ 验证: accessToken 字段存在 (camelCase) ✓
|
||
✅ 验证: refreshToken 字段存在 (camelCase) ✓
|
||
✅ 验证: userId 字段存在 (camelCase) ✓
|
||
|
||
步骤 4: 测试创建集群 API (camelCase)
|
||
✅ 集群创建成功!
|
||
Cluster ID: cluster-1731240123456
|
||
✅ 验证: createdAt 字段存在 (camelCase) ✓
|
||
✅ 验证: hasCaData 字段存在 (camelCase) ✓
|
||
|
||
步骤 5: 测试获取集群列表
|
||
✅ 获取集群列表成功,字段使用 camelCase ✓
|
||
|
||
步骤 6: 测试 Registry API (camelCase)
|
||
✅ Registry API 使用 camelCase ✓
|
||
|
||
================================
|
||
🎉 API 测试完成!
|
||
|
||
测试总结:
|
||
✅ 后端服务运行正常
|
||
✅ JSON 字段使用 camelCase 格式
|
||
✅ 前后端通信正常
|
||
```
|
||
|
||
## 🐛 故障排查
|
||
|
||
### 问题 1: 后端未启动
|
||
|
||
**症状:** `Connection refused`
|
||
|
||
**解决:**
|
||
```bash
|
||
cd backend
|
||
make run-mock
|
||
```
|
||
|
||
### 问题 2: 字段仍是 snake_case
|
||
|
||
**检查:**
|
||
1. 确认 Go DTO JSON tags 已更新
|
||
2. 确认 OpenAPI 规范已更新
|
||
3. 重新编译后端:`go build`
|
||
4. 清除缓存并重启
|
||
|
||
### 问题 3: 前端类型不匹配
|
||
|
||
**检查:**
|
||
1. 确认前端代码已重新生成:`npm run openapi-gen`
|
||
2. 检查生成的类型:`cat src/api/generated-orval/api.schemas.ts | grep CreateClusterRequest -A 10`
|
||
3. 重启 TypeScript 服务器(VSCode: Cmd/Ctrl + Shift + P → "TypeScript: Restart TS Server")
|
||
|
||
### 问题 4: 401 Unauthorized
|
||
|
||
**解决:**
|
||
1. 确保先调用登录 API 获取 token
|
||
2. 在请求头中正确设置:`Authorization: Bearer <token>`
|
||
3. 或使用前端的 `setAuthToken()` 函数
|
||
|
||
## 📚 相关文档
|
||
|
||
- `CAMELCASE-MIGRATION.md` - 迁移总结
|
||
- `frontend/src/api/README.md` - API 使用文档
|
||
- `frontend/src/api/example.ts` - 代码示例
|
||
|
||
## ✅ 完成标志
|
||
|
||
当你看到以下结果时,说明测试成功:
|
||
|
||
1. ✅ 后端 API 返回 camelCase JSON
|
||
2. ✅ 前端可以正确解析 camelCase 响应
|
||
3. ✅ 前端发送 camelCase 请求
|
||
4. ✅ 后端可以正确解析 camelCase 请求
|
||
5. ✅ TypeScript 类型提示正常工作
|
||
6. ✅ 所有 API 调用成功
|
||
|
||
🎉 **恭喜!你的 camelCase API 已经完全正常工作!**
|
||
|