1259 lines
26 KiB
Markdown
1259 lines
26 KiB
Markdown
# 资产服务和点赞服务 HTTP 完整测试流程
|
||
|
||
## 目录
|
||
|
||
1. [环境准备](#环境准备)
|
||
2. [服务启动](#服务启动)
|
||
3. [用户准备](#用户准备)
|
||
4. [资产功能测试](#资产功能测试)
|
||
5. [点赞功能测试](#点赞功能测试)
|
||
6. [异常场景测试](#异常场景测试)
|
||
7. [测试数据清理](#测试数据清理)
|
||
8. [常见问题](#常见问题)
|
||
|
||
---
|
||
|
||
## 环境准备
|
||
|
||
### 1. 数据库准备
|
||
|
||
确保 PostgreSQL 数据库已启动并创建了 `top-fans` 数据库:
|
||
|
||
```sql
|
||
CREATE DATABASE "top-fans" OWNER haihuizhu ENCODING 'UTF8';
|
||
```
|
||
|
||
### 2. 环境变量配置
|
||
|
||
```bash
|
||
# Gateway 配置
|
||
export SERVER_PORT=8080
|
||
export GIN_MODE=debug
|
||
export DUBBO_USER_SERVICE_URL="tri://127.0.0.1:20000"
|
||
export DUBBO_SOCIAL_SERVICE_URL="tri://127.0.0.1:20001"
|
||
export DUBBO_ASSET_SERVICE_URL="tri://127.0.0.1:20002"
|
||
export JWT_SECRET="topfans-secret-key-please-change-in-production"
|
||
```
|
||
|
||
### 3. 工具准备
|
||
|
||
推荐使用以下工具之一进行API测试:
|
||
- **Postman** (推荐)
|
||
- **curl** 命令行
|
||
- **HTTPie**
|
||
- **Insomnia**
|
||
|
||
### 4. 测试数据准备
|
||
|
||
确保数据库中有明星数据:
|
||
|
||
```sql
|
||
-- 肖战(identity_id: xz)
|
||
INSERT INTO stars (star_id, name, tag, name_en, pic_url, description, identity_id, is_active, created_at, updated_at)
|
||
VALUES (87, '肖战', '小飞侠', 'xiaozhan', '', '', 'xz', true, 1767590443835, 1767590443835)
|
||
ON CONFLICT (star_id) DO NOTHING;
|
||
|
||
-- 王一博(identity_id: wyb)
|
||
INSERT INTO stars (star_id, name, tag, name_en, pic_url, description, identity_id, is_active, created_at, updated_at)
|
||
VALUES (88, '王一博', '小摩托', 'wangyibo', '', '', 'wyb', true, 1767590443835, 1767590443835)
|
||
ON CONFLICT (star_id) DO NOTHING;
|
||
```
|
||
|
||
---
|
||
|
||
## 服务启动
|
||
|
||
### 1. 启动 UserService
|
||
|
||
```bash
|
||
cd /Users/haihuizhu/infinite_matrix/TopFans/backend/services/userService
|
||
go run main.go
|
||
```
|
||
|
||
**预期输出:**
|
||
```
|
||
Starting User Service...
|
||
Dubbo-go service started successfully. Press Ctrl+C to exit.
|
||
```
|
||
|
||
**检查端口:**
|
||
```bash
|
||
lsof -i :20000
|
||
```
|
||
|
||
### 2. 启动 SocialService
|
||
|
||
```bash
|
||
cd /Users/haihuizhu/infinite_matrix/TopFans/backend/services/socialService
|
||
go run main.go
|
||
```
|
||
|
||
**预期输出:**
|
||
```
|
||
Starting Social Service...
|
||
Social service started successfully. Press Ctrl+C to exit.
|
||
```
|
||
|
||
**检查端口:**
|
||
```bash
|
||
lsof -i :20001
|
||
```
|
||
|
||
### 3. 启动 AssetService
|
||
|
||
```bash
|
||
cd /Users/haihuizhu/infinite_matrix/TopFans/backend/services/assetService
|
||
go run main.go
|
||
```
|
||
|
||
**预期输出:**
|
||
```
|
||
Starting Asset Service...
|
||
Asset Service started successfully on port 20002
|
||
```
|
||
|
||
**检查端口:**
|
||
```bash
|
||
lsof -i :20002
|
||
```
|
||
|
||
### 4. 启动 Gateway
|
||
|
||
```bash
|
||
cd /Users/haihuizhu/infinite_matrix/TopFans/backend/gateway
|
||
go run main.go
|
||
```
|
||
|
||
**预期输出:**
|
||
```
|
||
Starting Top-Fans Gateway...
|
||
Gateway server started successfully
|
||
```
|
||
|
||
**检查端口:**
|
||
```bash
|
||
lsof -i :8080
|
||
```
|
||
|
||
### 5. 健康检查
|
||
|
||
```bash
|
||
curl http://localhost:8080/health
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"service": "top-fans-gateway"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 用户准备
|
||
|
||
### 步骤 1: 注册用户 A(张三)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"mobile": "13800000001",
|
||
"password": "password123",
|
||
"star_id": 87,
|
||
"nickname": "张三"
|
||
}'
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"token_expires_at": 1736234567890,
|
||
"user": {
|
||
"id": 1,
|
||
"mobile": "13800000001",
|
||
"avatar_url": "",
|
||
"is_active": true
|
||
},
|
||
"fan_profile": {
|
||
"id": 1,
|
||
"user_id": 1,
|
||
"star_id": 87,
|
||
"nickname": "张三",
|
||
"level": 1,
|
||
"social": 0
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**保存变量:**
|
||
```bash
|
||
export USER_A_ID=1
|
||
export USER_A_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
```
|
||
|
||
### 步骤 2: 注册用户 B(李四)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"mobile": "13800000002",
|
||
"password": "password123",
|
||
"star_id": 87,
|
||
"nickname": "李四"
|
||
}'
|
||
```
|
||
|
||
**保存变量:**
|
||
```bash
|
||
export USER_B_ID=2
|
||
export USER_B_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
```
|
||
|
||
### 步骤 3: 注册用户 C(王五)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"mobile": "13800000003",
|
||
"password": "password123",
|
||
"star_id": 87,
|
||
"nickname": "王五"
|
||
}'
|
||
```
|
||
|
||
**保存变量:**
|
||
```bash
|
||
export USER_C_ID=3
|
||
export USER_C_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
```
|
||
|
||
---
|
||
|
||
## 资产功能测试
|
||
|
||
### API 概览
|
||
|
||
| 序号 | 功能 | 方法 | 路径 | 说明 |
|
||
|------|------|------|------|------|
|
||
| 1 | 上传图片 | POST | `/api/v1/assets/upload` | 上传藏品图片(返回URL) |
|
||
| 2 | 创建铸造订单 | POST | `/api/v1/assets/mints` | 创建资产并发起铸造 |
|
||
| 3 | 取消铸造订单 | DELETE | `/api/v1/assets/mints/{order_id}` | 取消铸造订单(不退回水晶) |
|
||
| 4 | 获取我的藏品列表 | GET | `/api/v1/assets/me/items` | 获取当前用户的藏品列表(含点赞数) |
|
||
| 5 | 获取资产详情 | GET | `/api/v1/assets/{asset_id}` | 获取资产详细信息(仅限自己的资产) |
|
||
| 6 | 查询上链状态 | GET | `/api/v1/assets/{asset_id}/status` | 查询资产上链状态(仅限自己的资产) |
|
||
|
||
---
|
||
|
||
### 测试场景 0: 上传图片(可选)
|
||
|
||
#### 0.1 上传封面图片
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/assets/upload \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" \
|
||
-d '{
|
||
"image_url": "https://example.com/images/cover1.jpg",
|
||
"type": "cover"
|
||
}'
|
||
```
|
||
|
||
**请求参数说明:**
|
||
- `image_url` (必填): 图片URL
|
||
- `type` (可选): 图片类型,可选值:`cover`(封面,默认) 或 `material`(素材)
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"pic_url": "https://example.com/images/cover1.jpg",
|
||
"upload_id": "upload_1736234567_abc12345"
|
||
}
|
||
}
|
||
```
|
||
|
||
**说明:** 目前直接返回原URL,后续可扩展图片审核、AI处理等功能。
|
||
|
||
---
|
||
|
||
### 测试场景 1: 创建铸造订单
|
||
|
||
#### 1.1 张三创建第一个资产(包含所有可选参数)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/assets/mints \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" \
|
||
-d '{
|
||
"name": "肖战的第一个藏品",
|
||
"cover_url": "https://example.com/images/cover1.jpg",
|
||
"material_url": "https://example.com/materials/material1.jpg",
|
||
"description": "这是张三创建的第一个藏品,非常珍贵!",
|
||
"rarity": 5,
|
||
"tags": ["限量", "珍藏", "肖战"]
|
||
}'
|
||
```
|
||
|
||
**请求参数说明:**
|
||
- `name` (必填): 藏品名称
|
||
- `cover_url` (必填): 封面图URL
|
||
- `material_url` (可选): 用户上传的素材URL
|
||
- `description` (可选): 藏品描述
|
||
- `rarity` (可选): 稀有度(整数)
|
||
- `tags` (可选): 标签列表(字符串数组)
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"order": {
|
||
"order_id": "550e8400-e29b-41d4-a716-446655440000",
|
||
"user_id": 1,
|
||
"asset_id": 1,
|
||
"star_id": 87,
|
||
"status": "PENDING",
|
||
"cost_crystal": 100,
|
||
"retry_count": 0,
|
||
"created_at": 1736234567890,
|
||
"updated_at": 1736234567890
|
||
},
|
||
"asset": {
|
||
"asset_id": 1,
|
||
"owner_uid": 1,
|
||
"star_id": 87,
|
||
"name": "肖战的第一个藏品",
|
||
"cover_url": "https://example.com/images/cover1.jpg",
|
||
"material_url": "https://example.com/materials/material1.jpg",
|
||
"description": "这是张三创建的第一个藏品,非常珍贵!",
|
||
"rarity": 5,
|
||
"tags": ["限量", "珍藏", "肖战"],
|
||
"status": 0,
|
||
"like_count": 0,
|
||
"created_at": 1736234567890,
|
||
"updated_at": 1736234567890
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**保存变量:**
|
||
```bash
|
||
export ASSET_A1_ID=1
|
||
export ORDER_A1_ID="550e8400-e29b-41d4-a716-446655440000"
|
||
```
|
||
|
||
#### 1.2 张三创建第二个资产(仅必填参数)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/assets/mints \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" \
|
||
-d '{
|
||
"name": "肖战的第二个藏品",
|
||
"cover_url": "https://example.com/images/cover2.jpg"
|
||
}'
|
||
```
|
||
|
||
**说明:** 此请求仅包含必填参数 `name` 和 `cover_url`,其他参数均为可选。
|
||
|
||
**保存变量:**
|
||
```bash
|
||
export ASSET_A2_ID=2
|
||
```
|
||
|
||
#### 1.3 李四创建资产
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/assets/mints \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}" \
|
||
-d '{
|
||
"name": "李四的珍藏",
|
||
"cover_url": "https://example.com/images/cover3.jpg",
|
||
"description": "这是李四创建的藏品",
|
||
"rarity": 4,
|
||
"tags": ["珍藏"]
|
||
}'
|
||
```
|
||
|
||
**保存变量:**
|
||
```bash
|
||
export ASSET_B1_ID=3
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 2: 取消铸造订单
|
||
|
||
#### 2.1 张三取消第二个铸造订单
|
||
|
||
```bash
|
||
curl -X DELETE "http://localhost:8080/api/v1/assets/mints/${ORDER_A2_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"order_id": "550e8400-e29b-41d4-a716-446655440001",
|
||
"status": "CANCELLED"
|
||
}
|
||
}
|
||
```
|
||
|
||
**说明:**
|
||
- 只有 `PENDING` 或 `FAILED` 状态的订单才能取消
|
||
- 取消订单不会退回已扣除的水晶
|
||
- 取消后订单状态变为 `CANCELLED`
|
||
|
||
---
|
||
|
||
### 测试场景 3: 获取我的藏品列表
|
||
|
||
#### 3.1 获取张三的藏品列表(默认分页)
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me/items" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"items": [
|
||
{
|
||
"asset_id": 2,
|
||
"name": "肖战的第二个藏品",
|
||
"cover_url": "https://example.com/images/cover2.jpg",
|
||
"status": "pending",
|
||
"created_at": 1736234600000,
|
||
"minted_at": 0,
|
||
"like_count": 0
|
||
},
|
||
{
|
||
"asset_id": 1,
|
||
"name": "肖战的第一个藏品",
|
||
"cover_url": "https://example.com/images/cover1.jpg",
|
||
"status": "pending",
|
||
"created_at": 1736234567890,
|
||
"minted_at": 0,
|
||
"like_count": 0
|
||
}
|
||
],
|
||
"total": 2,
|
||
"page": 1,
|
||
"page_size": 20,
|
||
"has_more": false
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2 获取张三的藏品列表(分页查询)
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me/items?page=1&page_size=1" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"items": [
|
||
{
|
||
"asset_id": 2,
|
||
"name": "肖战的第二个藏品",
|
||
"cover_url": "https://example.com/images/cover2.jpg",
|
||
"status": "pending",
|
||
"created_at": 1736234600000,
|
||
"minted_at": 0
|
||
}
|
||
],
|
||
"total": 2,
|
||
"page": 1,
|
||
"page_size": 1,
|
||
"has_more": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.3 按状态筛选藏品
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me/items?status=pending" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
#### 2.4 关键词搜索藏品
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me?keyword=第一个" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"items": [
|
||
{
|
||
"asset_id": 1,
|
||
"name": "肖战的第一个藏品",
|
||
"cover_url": "https://example.com/images/cover1.jpg",
|
||
"status": "pending",
|
||
"created_at": 1736234567890,
|
||
"minted_at": 0
|
||
}
|
||
],
|
||
"total": 1,
|
||
"page": 1,
|
||
"page_size": 20,
|
||
"has_more": false
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.5 按创建时间排序
|
||
|
||
```bash
|
||
# 降序(默认)
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me?sort=created_at_desc" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
|
||
# 升序
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me?sort=created_at_asc" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
|
||
# 按名称排序
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me?sort=name_asc" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 4: 获取资产详情
|
||
|
||
#### 3.1 获取张三的第一个资产详情
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_A1_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"owner_uid": 1,
|
||
"star_id": 87,
|
||
"name": "肖战的第一个藏品",
|
||
"cover_url": "https://example.com/images/cover1.jpg",
|
||
"material_url": "https://example.com/materials/material1.jpg",
|
||
"description": "这是张三创建的第一个藏品,非常珍贵!",
|
||
"rarity": 5,
|
||
"tags": ["限量", "珍藏", "肖战"],
|
||
"visibility": "public",
|
||
"status": 0,
|
||
"like_count": 0,
|
||
"created_at": 1736234567890,
|
||
"updated_at": 1736234567890,
|
||
"minted_at": 0,
|
||
"owner": {
|
||
"user_id": 1,
|
||
"nickname": "张三",
|
||
"avatar": ""
|
||
},
|
||
"is_liked": false
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.2 尝试获取别人的资产(应该失败)
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_B1_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"message": "You can only view your own assets",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 5: 查询上链状态
|
||
|
||
#### 4.1 查询资产上链状态
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_A1_ID}/status" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"status": "pending",
|
||
"tx_hash": "",
|
||
"block_number": 0,
|
||
"minted_at": 0,
|
||
"error_message": ""
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
---
|
||
|
||
## 点赞功能测试
|
||
|
||
### API 概览
|
||
|
||
| 序号 | 功能 | 方法 | 路径 | 说明 |
|
||
|------|------|------|------|------|
|
||
| 1 | 点赞资产 | POST | `/api/v1/social/assets/{asset_id}/like` | 点赞指定资产 |
|
||
| 2 | 取消点赞 | DELETE | `/api/v1/social/assets/{asset_id}/like` | 取消点赞指定资产 |
|
||
| 3 | 检查是否已点赞 | GET | `/api/v1/social/assets/{asset_id}/like` | 检查当前用户是否已点赞该资产 |
|
||
|
||
---
|
||
|
||
### 测试场景 1: 点赞资产
|
||
|
||
#### 1.1 李四点赞张三的第一个资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"new_like_count": 1,
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 1.2 王五点赞张三的第一个资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_C_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"new_like_count": 2,
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 1.3 张三自己点赞自己的资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"new_like_count": 3,
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 1.4 验证资产详情中的点赞数
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_A1_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应(部分):**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"like_count": 3,
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 2: 检查是否已点赞
|
||
|
||
#### 2.1 李四检查是否已点赞
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2 未点赞的用户检查(应该返回 false)
|
||
|
||
```bash
|
||
# 假设有一个新用户 USER_D,未点赞该资产
|
||
curl -X GET "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_D_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"is_liked": false
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 3: 取消点赞
|
||
|
||
#### 3.1 李四取消点赞
|
||
|
||
```bash
|
||
curl -X DELETE "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"new_like_count": 2,
|
||
"is_liked": false
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.2 验证点赞数已减少
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_A1_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应(部分):**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"like_count": 2,
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.3 再次检查李四的点赞状态
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"is_liked": false
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 4: 重复点赞处理
|
||
|
||
#### 4.1 尝试重复点赞(应该返回已点赞状态)
|
||
|
||
```bash
|
||
# 王五已经点赞过,再次点赞
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_C_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "Asset already liked by this user",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"new_like_count": 2,
|
||
"is_liked": true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 5: 取消未点赞的资产
|
||
|
||
#### 5.1 尝试取消未点赞的资产
|
||
|
||
```bash
|
||
# 李四已经取消点赞,再次取消
|
||
curl -X DELETE "http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "Asset not liked by this user",
|
||
"data": {
|
||
"asset_id": 1,
|
||
"new_like_count": 2,
|
||
"is_liked": false
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 6: 多个资产的点赞测试
|
||
|
||
#### 6.1 李四点赞张三的第二个资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/${ASSET_A2_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
#### 6.2 王五点赞张三的第二个资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/${ASSET_A2_ID}/like" \
|
||
-H "Authorization: Bearer ${USER_C_TOKEN}"
|
||
```
|
||
|
||
#### 6.3 验证两个资产的点赞数
|
||
|
||
```bash
|
||
# 资产1的点赞数
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_A1_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" | jq '.data.like_count'
|
||
|
||
# 资产2的点赞数
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_A2_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" | jq '.data.like_count'
|
||
```
|
||
|
||
---
|
||
|
||
## 异常场景测试
|
||
|
||
### 异常场景 1: 未授权访问
|
||
|
||
#### 1.1 未登录创建资产
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/assets/mints \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"name": "测试资产",
|
||
"cover_url": "https://example.com/images/test.jpg"
|
||
}'
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 401,
|
||
"message": "Unauthorized",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 1.2 未登录点赞资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/1/like"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 401,
|
||
"message": "Unauthorized",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 异常场景 2: 无效的资产ID
|
||
|
||
#### 2.1 获取不存在的资产详情
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/99999" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"message": "Asset not found",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 2.2 点赞不存在的资产
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/social/assets/99999/like" \
|
||
-H "Authorization: Bearer ${USER_B_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"message": "Asset not found",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 异常场景 3: 访问别人的资产
|
||
|
||
#### 3.1 尝试获取别人的资产详情
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_B1_ID}" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"message": "You can only view your own assets",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 3.2 尝试查询别人的资产状态
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/${ASSET_B1_ID}/status" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"message": "You can only view your own assets",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 异常场景 4: 无效的请求参数
|
||
|
||
#### 4.1 创建资产时缺少必填字段
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/v1/assets/mints \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" \
|
||
-d '{
|
||
"name": "测试资产"
|
||
}'
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "cover_url is required",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 4.2 无效的分页参数
|
||
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/assets/me?page=-1&page_size=0" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}"
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "ok",
|
||
"data": {
|
||
"items": [],
|
||
"total": 2,
|
||
"page": 1,
|
||
"page_size": 20,
|
||
"has_more": false
|
||
}
|
||
}
|
||
```
|
||
|
||
**说明:** 系统会自动修正无效的分页参数。
|
||
|
||
---
|
||
|
||
### 异常场景 5: 水晶余额不足
|
||
|
||
#### 5.1 创建资产时水晶不足
|
||
|
||
**前提条件:** 用户的水晶余额小于创建资产所需的水晶数(100)
|
||
|
||
```bash
|
||
# 假设用户水晶余额为 50
|
||
curl -X POST http://localhost:8080/api/v1/assets/mints \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer ${USER_A_TOKEN}" \
|
||
-d '{
|
||
"name": "测试资产",
|
||
"cover_url": "https://example.com/images/test.jpg"
|
||
}'
|
||
```
|
||
|
||
**预期响应:**
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "Insufficient crystal balance",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 测试数据清理
|
||
|
||
### 清理测试资产
|
||
|
||
```sql
|
||
-- 删除测试用户的资产点赞记录
|
||
DELETE FROM asset_likes
|
||
WHERE user_id IN (
|
||
SELECT id FROM users WHERE mobile IN ('13800000001', '13800000002', '13800000003')
|
||
);
|
||
|
||
-- 删除测试用户的资产
|
||
DELETE FROM assets
|
||
WHERE owner_uid IN (
|
||
SELECT id FROM users WHERE mobile IN ('13800000001', '13800000002', '13800000003')
|
||
);
|
||
|
||
-- 删除测试用户的铸造订单
|
||
DELETE FROM mint_orders
|
||
WHERE user_id IN (
|
||
SELECT id FROM users WHERE mobile IN ('13800000001', '13800000002', '13800000003')
|
||
);
|
||
```
|
||
|
||
### 清理测试用户
|
||
|
||
```sql
|
||
-- 删除测试用户的粉丝档案
|
||
DELETE FROM fan_profiles
|
||
WHERE user_id IN (
|
||
SELECT id FROM users WHERE mobile IN ('13800000001', '13800000002', '13800000003')
|
||
);
|
||
|
||
-- 删除测试用户
|
||
DELETE FROM users
|
||
WHERE mobile IN ('13800000001', '13800000002', '13800000003');
|
||
```
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 创建资产时提示 "Insufficient crystal balance"
|
||
|
||
**原因:** 用户的水晶余额不足。
|
||
|
||
**解决方案:**
|
||
1. 检查用户的水晶余额
|
||
2. 确保用户有足够的水晶(创建资产需要 100 水晶)
|
||
3. 可以通过用户服务接口充值水晶(如果已实现)
|
||
|
||
### Q2: 无法获取别人的资产详情
|
||
|
||
**原因:** 系统设计为只能查看自己的资产。
|
||
|
||
**解决方案:** 这是正常的安全限制,无法绕过。如果需要查看别人的资产,需要实现新的接口或修改权限控制。
|
||
|
||
### Q3: 点赞数不更新
|
||
|
||
**可能原因:**
|
||
1. Asset Service 未启动
|
||
2. Social Service 和 Asset Service 之间的 RPC 调用失败
|
||
3. 数据库事务未提交
|
||
|
||
**解决方案:**
|
||
1. 检查所有服务是否正常运行
|
||
2. 查看服务日志,确认 RPC 调用是否成功
|
||
3. 检查数据库连接和事务状态
|
||
|
||
### Q4: 重复点赞返回成功但点赞数未增加
|
||
|
||
**原因:** 系统检测到重复点赞,返回成功但不会增加点赞数。
|
||
|
||
**解决方案:** 这是正常行为。系统会返回 `"message": "Asset already liked by this user"`,表示已点赞。
|
||
|
||
### Q5: 资产状态一直是 "pending"
|
||
|
||
**原因:** 上链功能可能未实现或正在处理中。
|
||
|
||
**解决方案:**
|
||
1. 检查上链服务是否正常运行
|
||
2. 查看订单状态和错误信息
|
||
3. 如果上链功能未实现,这是正常的(设计文档中说明上链为异步处理)
|
||
|
||
### Q6: 分页查询返回的数据顺序不一致
|
||
|
||
**原因:** 未指定排序方式。
|
||
|
||
**解决方案:** 使用 `sort` 参数指定排序方式:
|
||
- `created_at_desc` - 按创建时间降序(默认)
|
||
- `created_at_asc` - 按创建时间升序
|
||
- `name_asc` - 按名称升序
|
||
|
||
---
|
||
|
||
## 完整测试流程总结
|
||
|
||
### 推荐测试顺序
|
||
|
||
1. **环境准备** → 启动所有服务
|
||
2. **用户准备** → 注册测试用户
|
||
3. **资产创建** → 创建多个测试资产
|
||
4. **资产查询** → 测试列表、详情、状态查询
|
||
5. **点赞功能** → 测试点赞、取消点赞、检查状态
|
||
6. **异常场景** → 测试各种错误情况
|
||
7. **数据清理** → 清理测试数据
|
||
|
||
### 测试检查清单
|
||
|
||
- [ ] 所有服务正常启动
|
||
- [ ] 用户注册成功
|
||
- [ ] 创建资产成功
|
||
- [ ] 获取资产列表成功
|
||
- [ ] 获取资产详情成功
|
||
- [ ] 点赞资产成功
|
||
- [ ] 取消点赞成功
|
||
- [ ] 检查点赞状态成功
|
||
- [ ] 点赞数正确更新
|
||
- [ ] 异常场景处理正确
|
||
- [ ] 权限控制正确
|
||
- [ ] 数据隔离正确(不同明星的数据互不干扰)
|
||
|
||
---
|
||
|
||
## 性能测试建议
|
||
|
||
### 1. 并发点赞测试
|
||
|
||
```bash
|
||
# 使用 Apache Bench 进行并发点赞测试
|
||
ab -n 100 -c 10 -H "Authorization: Bearer ${USER_B_TOKEN}" \
|
||
-X POST http://localhost:8080/api/v1/social/assets/${ASSET_A1_ID}/like
|
||
```
|
||
|
||
### 2. 大量资产查询测试
|
||
|
||
创建 100+ 个资产,测试分页查询性能。
|
||
|
||
### 3. 点赞数统计测试
|
||
|
||
创建资产并让多个用户点赞,验证点赞数统计的准确性。
|
||
|
||
---
|
||
|
||
**文档版本**: v1.0
|
||
**最后更新**: 2026-01-12
|
||
**维护者**: AI Assistant
|