topfans/backend/docs/资产服务和点赞服务HTTP完整测试流程.md
2026-04-07 22:29:48 +08:00

1259 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 资产服务和点赞服务 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