This commit is contained in:
parent
4fbca69942
commit
f9a0f95cab
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Test Environment Configuration
|
||||||
|
|
||||||
|
# Database - 使用测试数据库
|
||||||
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity_test?schema=public"
|
||||||
|
|
||||||
|
# JWT
|
||||||
|
JWT_SECRET="test-jwt-secret-key-for-e2e-tests"
|
||||||
|
JWT_ACCESS_EXPIRES_IN="2h"
|
||||||
|
JWT_REFRESH_EXPIRES_IN="30d"
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
REDIS_HOST="localhost"
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_PASSWORD=""
|
||||||
|
REDIS_DB=1
|
||||||
|
|
||||||
|
# Kafka - 测试环境
|
||||||
|
KAFKA_BROKERS="localhost:9092"
|
||||||
|
KAFKA_CLIENT_ID="identity-service-test"
|
||||||
|
KAFKA_GROUP_ID="identity-service-test-group"
|
||||||
|
|
||||||
|
# SMS Service - 可以使用mock
|
||||||
|
SMS_API_URL="https://sms-api.example.com"
|
||||||
|
SMS_API_KEY="test-sms-api-key"
|
||||||
|
|
||||||
|
# App
|
||||||
|
APP_PORT=3001
|
||||||
|
APP_ENV="test"
|
||||||
|
|
||||||
|
# Blockchain Encryption
|
||||||
|
WALLET_ENCRYPTION_SALT="test-wallet-salt"
|
||||||
|
|
@ -45,7 +45,20 @@ npm install
|
||||||
- `supertest@^6.3.3` - HTTP 断言库
|
- `supertest@^6.3.3` - HTTP 断言库
|
||||||
- `@types/supertest@^6.0.0` - TypeScript 类型定义
|
- `@types/supertest@^6.0.0` - TypeScript 类型定义
|
||||||
|
|
||||||
### 2. 运行所有单元测试
|
### 2. 准备 E2E 测试环境
|
||||||
|
|
||||||
|
E2E 测试需要数据库和 Redis,但 **不需要** Kafka(已使用 Mock)。
|
||||||
|
|
||||||
|
详细设置请参阅: [E2E_TEST_SETUP.md](E2E_TEST_SETUP.md)
|
||||||
|
|
||||||
|
快速开始:
|
||||||
|
```bash
|
||||||
|
# 确保 PostgreSQL 和 Redis 正在运行
|
||||||
|
# 准备测试数据库
|
||||||
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity_test?schema=public" npx prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 运行所有单元测试
|
||||||
```bash
|
```bash
|
||||||
npm test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
@ -60,11 +73,17 @@ Test Suites: 3 passed, 3 total
|
||||||
Tests: 30+ passed, 30+ total
|
Tests: 30+ passed, 30+ total
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 运行 E2E 测试
|
### 4. 运行 E2E 测试
|
||||||
```bash
|
```bash
|
||||||
npm run test:e2e
|
npm run test:e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**注意**: E2E 测试需要:
|
||||||
|
- ✅ PostgreSQL 数据库(测试数据库)
|
||||||
|
- ✅ Redis 服务
|
||||||
|
- ❌ **不需要** Kafka(已使用 Mock)
|
||||||
|
- ❌ **不需要** SMS 服务(已使用 Mock)
|
||||||
|
|
||||||
**预期输出**:
|
**预期输出**:
|
||||||
```
|
```
|
||||||
PASS test/app.e2e-spec.ts
|
PASS test/app.e2e-spec.ts
|
||||||
|
|
@ -76,9 +95,11 @@ PASS test/app.e2e-spec.ts
|
||||||
...
|
...
|
||||||
|
|
||||||
Test Suites: 1 passed, 1 total
|
Test Suites: 1 passed, 1 total
|
||||||
Tests: 40+ passed, 40+ total
|
Tests: 20+ passed, 20+ total
|
||||||
```
|
```
|
||||||
|
|
||||||
|
如果遇到问题,请参阅 [E2E_TEST_SETUP.md](E2E_TEST_SETUP.md)
|
||||||
|
|
||||||
### 4. 查看测试覆盖率
|
### 4. 查看测试覆盖率
|
||||||
```bash
|
```bash
|
||||||
npm run test:cov
|
npm run test:cov
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
# E2E 测试设置指南
|
||||||
|
|
||||||
|
## 前置条件
|
||||||
|
|
||||||
|
E2E测试需要以下服务运行:
|
||||||
|
|
||||||
|
### 1. PostgreSQL 数据库
|
||||||
|
|
||||||
|
测试使用独立的测试数据库,不会影响开发数据库。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 确保 PostgreSQL 正在运行
|
||||||
|
# 创建测试数据库(如果还没有)
|
||||||
|
createdb rwa_identity_test
|
||||||
|
|
||||||
|
# 或使用 psql
|
||||||
|
psql -U postgres
|
||||||
|
CREATE DATABASE rwa_identity_test;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Redis (可选)
|
||||||
|
|
||||||
|
测试需要 Redis 用于 Token 管理。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动 Redis(如果还没运行)
|
||||||
|
redis-server
|
||||||
|
|
||||||
|
# 或使用 Docker
|
||||||
|
docker run -d -p 6379:6379 redis:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 配置测试环境变量
|
||||||
|
|
||||||
|
已创建 `.env.test` 文件,包含测试环境配置:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity_test?schema=public"
|
||||||
|
REDIS_HOST="localhost"
|
||||||
|
REDIS_PORT=6379
|
||||||
|
JWT_SECRET="test-jwt-secret-key-for-e2e-tests"
|
||||||
|
WALLET_ENCRYPTION_SALT="test-wallet-salt"
|
||||||
|
```
|
||||||
|
|
||||||
|
**重要**: 请根据你的本地环境修改数据库连接字符串中的用户名和密码。
|
||||||
|
|
||||||
|
## 运行测试步骤
|
||||||
|
|
||||||
|
### 1. 准备测试数据库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 生成 Prisma Client
|
||||||
|
npm run prisma:generate
|
||||||
|
|
||||||
|
# 运行数据库迁移(针对测试数据库)
|
||||||
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity_test?schema=public" npx prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 运行 E2E 测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 设置环境变量并运行测试
|
||||||
|
NODE_ENV=test npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 清理测试数据(可选)
|
||||||
|
|
||||||
|
E2E测试会在测试数据库中创建数据。如果需要清理:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 重置测试数据库
|
||||||
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity_test?schema=public" npx prisma migrate reset --skip-seed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mock 服务说明
|
||||||
|
|
||||||
|
E2E 测试已经配置了以下 Mock 服务,**不需要**真实的外部服务:
|
||||||
|
|
||||||
|
### ✅ Kafka (已 Mock)
|
||||||
|
- `EventPublisherService` 已被 mock
|
||||||
|
- 不需要运行 Kafka 服务器
|
||||||
|
- 事件发布操作会被记录但不会真实发送
|
||||||
|
|
||||||
|
### ✅ SMS 服务 (已 Mock)
|
||||||
|
- `SmsService` 已被 mock
|
||||||
|
- 不需要真实的 SMS API
|
||||||
|
- 验证码发送操作会自动成功
|
||||||
|
|
||||||
|
### ⚠️ 仍需要真实服务
|
||||||
|
|
||||||
|
- **PostgreSQL** - 需要真实数据库来测试数据持久化
|
||||||
|
- **Redis** - 需要真实 Redis 来测试 Token 缓存
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 问题 1: 数据库连接失败
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: Can't reach database server
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 确认 PostgreSQL 正在运行
|
||||||
|
2. 检查 `.env.test` 中的数据库连接字符串
|
||||||
|
3. 确认测试数据库已创建
|
||||||
|
|
||||||
|
### 问题 2: Redis 连接失败
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: connect ECONNREFUSED 127.0.0.1:6379
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 启动 Redis: `redis-server`
|
||||||
|
2. 或临时禁用 Redis(需要修改代码)
|
||||||
|
|
||||||
|
### 问题 3: Kafka 警告信息
|
||||||
|
|
||||||
|
```
|
||||||
|
KafkaJS v2.0.0 switched default partitioner
|
||||||
|
```
|
||||||
|
|
||||||
|
**说明**: 这只是警告,不影响测试运行。Kafka 已被 mock,不会真实连接。
|
||||||
|
|
||||||
|
可以设置环境变量禁用警告:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
KAFKAJS_NO_PARTITIONER_WARNING=1 npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题 4: 测试超时
|
||||||
|
|
||||||
|
```
|
||||||
|
Timeout - Async callback was not invoked within the 5000 ms timeout
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
- 确保数据库和 Redis 响应速度正常
|
||||||
|
- 增加 Jest 超时时间(在 jest-e2e.json 中配置)
|
||||||
|
|
||||||
|
## 测试覆盖范围
|
||||||
|
|
||||||
|
E2E 测试覆盖了以下功能:
|
||||||
|
|
||||||
|
1. ✅ 用户注册和账户创建
|
||||||
|
2. ✅ 用户资料管理
|
||||||
|
3. ✅ 设备管理(添加/删除/限制)
|
||||||
|
4. ✅ Token 刷新
|
||||||
|
5. ✅ 推荐系统
|
||||||
|
6. ✅ KYC 认证
|
||||||
|
7. ✅ 助记词恢复
|
||||||
|
8. ✅ 数据验证
|
||||||
|
|
||||||
|
总计: **20+ 个测试用例**
|
||||||
|
|
||||||
|
## 快速开始(一键命令)
|
||||||
|
|
||||||
|
如果你的环境已经配置好 PostgreSQL 和 Redis:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 准备测试数据库
|
||||||
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity_test?schema=public" npx prisma migrate dev
|
||||||
|
|
||||||
|
# 2. 运行测试
|
||||||
|
npm run test:e2e
|
||||||
|
|
||||||
|
# 3. 查看测试结果
|
||||||
|
# 所有测试通过后,你会看到类似输出:
|
||||||
|
# Test Suites: 1 passed, 1 total
|
||||||
|
# Tests: 20 passed, 20 total
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker 环境快速启动
|
||||||
|
|
||||||
|
如果你想使用 Docker 运行依赖服务:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动 PostgreSQL 和 Redis
|
||||||
|
docker-compose -f docker-compose.test.yml up -d
|
||||||
|
|
||||||
|
# 等待服务启动
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# 运行测试
|
||||||
|
npm run test:e2e
|
||||||
|
|
||||||
|
# 停止服务
|
||||||
|
docker-compose -f docker-compose.test.yml down
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **测试数据隔离**: 测试使用独立的测试数据库,不会影响开发环境
|
||||||
|
2. **Mock 服务**: Kafka 和 SMS 已被 mock,测试速度更快
|
||||||
|
3. **数据清理**: 每次测试运行可能会在数据库中留下数据,定期清理测试数据库
|
||||||
|
4. **并发问题**: 避免同时运行多个测试实例,可能导致数据冲突
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
- 查看 [AUTOMATED_TESTS_README.md](AUTOMATED_TESTS_README.md) 了解完整的测试体系
|
||||||
|
- 查看 [TEST_AUTOMATION_GUIDE.md](TEST_AUTOMATION_GUIDE.md) 了解如何编写新测试
|
||||||
|
|
@ -3,6 +3,8 @@ import { INestApplication, ValidationPipe } from '@nestjs/common';
|
||||||
import * as request from 'supertest';
|
import * as request from 'supertest';
|
||||||
import { AppModule } from '@/app.module';
|
import { AppModule } from '@/app.module';
|
||||||
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
|
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
|
||||||
|
import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service';
|
||||||
|
import { SmsService } from '@/infrastructure/external/sms/sms.service';
|
||||||
|
|
||||||
describe('Identity Service E2E Tests', () => {
|
describe('Identity Service E2E Tests', () => {
|
||||||
let app: INestApplication;
|
let app: INestApplication;
|
||||||
|
|
@ -14,10 +16,28 @@ describe('Identity Service E2E Tests', () => {
|
||||||
let referralCode: string;
|
let referralCode: string;
|
||||||
let deviceId: string;
|
let deviceId: string;
|
||||||
|
|
||||||
|
// Mock Kafka Event Publisher - 避免真实Kafka连接
|
||||||
|
const mockEventPublisher = {
|
||||||
|
publish: jest.fn().mockResolvedValue(undefined),
|
||||||
|
publishAll: jest.fn().mockResolvedValue(undefined),
|
||||||
|
onModuleInit: jest.fn().mockResolvedValue(undefined),
|
||||||
|
onModuleDestroy: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock SMS Service - 避免真实SMS API调用
|
||||||
|
const mockSmsService = {
|
||||||
|
sendVerificationCode: jest.fn().mockResolvedValue(true),
|
||||||
|
};
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const moduleFixture: TestingModule = await Test.createTestingModule({
|
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||||
imports: [AppModule],
|
imports: [AppModule],
|
||||||
}).compile();
|
})
|
||||||
|
.overrideProvider(EventPublisherService)
|
||||||
|
.useValue(mockEventPublisher)
|
||||||
|
.overrideProvider(SmsService)
|
||||||
|
.useValue(mockSmsService)
|
||||||
|
.compile();
|
||||||
|
|
||||||
app = moduleFixture.createNestApplication();
|
app = moduleFixture.createNestApplication();
|
||||||
|
|
||||||
|
|
@ -56,9 +76,15 @@ describe('Identity Service E2E Tests', () => {
|
||||||
deviceName: 'Test Device',
|
deviceName: 'Test Device',
|
||||||
provinceCode: '110000',
|
provinceCode: '110000',
|
||||||
cityCode: '110100',
|
cityCode: '110100',
|
||||||
})
|
});
|
||||||
.expect(201);
|
|
||||||
|
|
||||||
|
// 打印错误信息以便调试
|
||||||
|
if (response.status !== 201) {
|
||||||
|
console.error('Response status:', response.status);
|
||||||
|
console.error('Response body:', JSON.stringify(response.body, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(response.status).toBe(201);
|
||||||
expect(response.body.success).toBe(true);
|
expect(response.body.success).toBe(true);
|
||||||
expect(response.body.data).toHaveProperty('userId');
|
expect(response.body.data).toHaveProperty('userId');
|
||||||
expect(response.body.data).toHaveProperty('accountSequence');
|
expect(response.body.data).toHaveProperty('accountSequence');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue