style: 完善代码规范和测试覆盖
- 新增多个模块的单元测试文件,提升测试覆盖率 - 完善AI-Reading文档系统,包含7步代码检查流程 - 新增集成测试和属性测试框架 - 优化项目结构和配置文件 - 清理过时的规范文档,统一使用新的检查标准
This commit is contained in:
234
test/integration/zulip_accounts_database.spec.ts
Normal file
234
test/integration/zulip_accounts_database.spec.ts
Normal file
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
* Zulip账号关联服务数据库测试
|
||||
*
|
||||
* 功能描述:
|
||||
* - 专门测试数据库模式下的真实数据库操作
|
||||
* - 需要配置数据库环境变量才能运行
|
||||
* - 测试真实的CRUD操作和业务逻辑
|
||||
*
|
||||
* 运行条件:
|
||||
* - 需要设置环境变量:DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_NAME
|
||||
* - 数据库中需要存在 zulip_accounts 表
|
||||
*
|
||||
* @author angjustinl
|
||||
* @version 1.0.0
|
||||
* @since 2026-01-10
|
||||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { CacheModule } from '@nestjs/cache-manager';
|
||||
import { ZulipAccountsService } from '../../src/core/db/zulip_accounts/zulip_accounts.service';
|
||||
import { ZulipAccountsRepository } from '../../src/core/db/zulip_accounts/zulip_accounts.repository';
|
||||
import { ZulipAccounts } from '../../src/core/db/zulip_accounts/zulip_accounts.entity';
|
||||
import { Users } from '../../src/core/db/users/users.entity';
|
||||
import { AppLoggerService } from '../../src/core/utils/logger/logger.service';
|
||||
|
||||
/**
|
||||
* 检查是否配置了数据库
|
||||
*/
|
||||
function isDatabaseConfigured(): boolean {
|
||||
const requiredEnvVars = ['DB_HOST', 'DB_PORT', 'DB_USERNAME', 'DB_PASSWORD', 'DB_NAME'];
|
||||
return requiredEnvVars.every(varName => process.env[varName]);
|
||||
}
|
||||
|
||||
// 只有在配置了数据库时才运行这些测试
|
||||
const describeDatabase = isDatabaseConfigured() ? describe : describe.skip;
|
||||
|
||||
describeDatabase('ZulipAccountsService - Database Mode', () => {
|
||||
let service: ZulipAccountsService;
|
||||
let module: TestingModule;
|
||||
|
||||
// 只有在数据库配置完整时才输出这些信息
|
||||
if (isDatabaseConfigured()) {
|
||||
console.log('🗄️ 运行数据库模式测试');
|
||||
console.log('📊 使用真实数据库连接进行测试');
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
envFilePath: ['.env.test', '.env'],
|
||||
isGlobal: true,
|
||||
}),
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
host: process.env.DB_HOST,
|
||||
port: parseInt(process.env.DB_PORT || '3306'),
|
||||
username: process.env.DB_USERNAME,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME,
|
||||
entities: [ZulipAccounts, Users],
|
||||
synchronize: false,
|
||||
logging: false,
|
||||
}),
|
||||
TypeOrmModule.forFeature([ZulipAccounts, Users]),
|
||||
CacheModule.register({
|
||||
ttl: 300,
|
||||
max: 1000,
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
ZulipAccountsService,
|
||||
ZulipAccountsRepository,
|
||||
AppLoggerService,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ZulipAccountsService>(ZulipAccountsService);
|
||||
}, 30000); // 增加超时时间
|
||||
|
||||
afterAll(async () => {
|
||||
if (module) {
|
||||
await module.close();
|
||||
}
|
||||
});
|
||||
|
||||
// 生成唯一的测试数据
|
||||
const generateTestData = (suffix: string = Date.now().toString()) => {
|
||||
const timestamp = Date.now();
|
||||
const uniqueId = timestamp + Math.floor(Math.random() * 1000); // 添加随机数避免冲突
|
||||
return {
|
||||
gameUserId: uniqueId.toString(), // 使用纯数字字符串
|
||||
zulipUserId: parseInt(`8${timestamp.toString().slice(-5)}`),
|
||||
zulipEmail: `test_db_${timestamp}_${suffix}@example.com`,
|
||||
zulipFullName: `数据库测试用户_${timestamp}_${suffix}`,
|
||||
zulipApiKeyEncrypted: 'encrypted_api_key_for_db_test',
|
||||
status: 'active' as const,
|
||||
};
|
||||
};
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('Database CRUD Operations', () => {
|
||||
it('should create and retrieve account from database', async () => {
|
||||
const testData = generateTestData('crud');
|
||||
|
||||
// 创建账号
|
||||
const created = await service.create(testData);
|
||||
expect(created).toBeDefined();
|
||||
expect(created.gameUserId).toBe(testData.gameUserId);
|
||||
expect(created.zulipEmail).toBe(testData.zulipEmail);
|
||||
expect(created.status).toBe('active');
|
||||
|
||||
// 根据游戏用户ID查找
|
||||
const found = await service.findByGameUserId(testData.gameUserId);
|
||||
expect(found).toBeDefined();
|
||||
expect(found?.id).toBe(created.id);
|
||||
expect(found?.zulipUserId).toBe(testData.zulipUserId);
|
||||
|
||||
// 清理测试数据
|
||||
await service.deleteByGameUserId(testData.gameUserId);
|
||||
}, 15000);
|
||||
|
||||
it('should handle duplicate creation properly', async () => {
|
||||
const testData = generateTestData('duplicate');
|
||||
|
||||
// 创建第一个账号
|
||||
const created = await service.create(testData);
|
||||
expect(created).toBeDefined();
|
||||
|
||||
// 尝试创建重复账号,应该抛出异常
|
||||
await expect(service.create(testData)).rejects.toThrow();
|
||||
|
||||
// 清理测试数据
|
||||
await service.deleteByGameUserId(testData.gameUserId);
|
||||
}, 15000);
|
||||
|
||||
it('should update account in database', async () => {
|
||||
const testData = generateTestData('update');
|
||||
|
||||
// 创建账号
|
||||
const created = await service.create(testData);
|
||||
|
||||
// 更新账号
|
||||
const updated = await service.update(created.id, {
|
||||
zulipFullName: '更新后的用户名',
|
||||
status: 'inactive',
|
||||
});
|
||||
|
||||
expect(updated.zulipFullName).toBe('更新后的用户名');
|
||||
expect(updated.status).toBe('inactive');
|
||||
|
||||
// 清理测试数据
|
||||
await service.deleteByGameUserId(testData.gameUserId);
|
||||
}, 15000);
|
||||
|
||||
it('should delete account from database', async () => {
|
||||
const testData = generateTestData('delete');
|
||||
|
||||
// 创建账号
|
||||
const created = await service.create(testData);
|
||||
|
||||
// 删除账号
|
||||
const deleted = await service.delete(created.id);
|
||||
expect(deleted).toBe(true);
|
||||
|
||||
// 验证账号已被删除
|
||||
const found = await service.findByGameUserId(testData.gameUserId);
|
||||
expect(found).toBeNull();
|
||||
}, 15000);
|
||||
});
|
||||
|
||||
describe('Database Business Logic', () => {
|
||||
it('should check email existence in database', async () => {
|
||||
const testData = generateTestData('email_check');
|
||||
|
||||
// 邮箱不存在时应该返回false
|
||||
const notExists = await service.existsByEmail(testData.zulipEmail);
|
||||
expect(notExists).toBe(false);
|
||||
|
||||
// 创建账号
|
||||
await service.create(testData);
|
||||
|
||||
// 邮箱存在时应该返回true
|
||||
const exists = await service.existsByEmail(testData.zulipEmail);
|
||||
expect(exists).toBe(true);
|
||||
|
||||
// 清理测试数据
|
||||
await service.deleteByGameUserId(testData.gameUserId);
|
||||
}, 15000);
|
||||
|
||||
it('should get status statistics from database', async () => {
|
||||
const stats = await service.getStatusStatistics();
|
||||
|
||||
expect(typeof stats.active).toBe('number');
|
||||
expect(typeof stats.inactive).toBe('number');
|
||||
expect(typeof stats.suspended).toBe('number');
|
||||
expect(typeof stats.error).toBe('number');
|
||||
expect(typeof stats.total).toBe('number');
|
||||
expect(stats.total).toBe(stats.active + stats.inactive + stats.suspended + stats.error);
|
||||
}, 15000);
|
||||
|
||||
it('should verify account in database', async () => {
|
||||
const testData = generateTestData('verify');
|
||||
|
||||
// 创建账号
|
||||
await service.create(testData);
|
||||
|
||||
// 验证账号
|
||||
const result = await service.verifyAccount(testData.gameUserId);
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.isValid).toBe(true);
|
||||
expect(result.verifiedAt).toBeDefined();
|
||||
|
||||
// 清理测试数据
|
||||
await service.deleteByGameUserId(testData.gameUserId);
|
||||
}, 15000);
|
||||
});
|
||||
});
|
||||
|
||||
// 如果没有配置数据库,显示跳过信息
|
||||
if (!isDatabaseConfigured()) {
|
||||
console.log('⚠️ 数据库测试已跳过:未检测到数据库配置');
|
||||
console.log('💡 要运行数据库测试,请设置以下环境变量:');
|
||||
console.log(' - DB_HOST');
|
||||
console.log(' - DB_PORT');
|
||||
console.log(' - DB_USERNAME');
|
||||
console.log(' - DB_PASSWORD');
|
||||
console.log(' - DB_NAME');
|
||||
}
|
||||
Reference in New Issue
Block a user