/** * 管理员数据库管理集成测试 * * 功能描述: * - 测试管理员数据库管理的完整功能 * - 验证CRUD操作的正确性 * - 测试权限控制和错误处理 * - 验证响应格式的一致性 * * 测试覆盖: * - 用户管理功能测试 * - 用户档案管理功能测试 * - Zulip账号关联管理功能测试 * - 批量操作功能测试 * - 错误处理和边界条件测试 * * 最近修改: * - 2026-01-08: 注释规范优化 - 修正@author字段,更新版本号和修改记录 (修改者: moyin) * - 2026-01-08: 功能新增 - 创建管理员数据库管理集成测试 (修改者: assistant) * * @author moyin * @version 1.0.1 * @since 2026-01-08 * @lastModified 2026-01-08 */ import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AdminDatabaseController } from '../controllers/admin_database.controller'; import { DatabaseManagementService } from '../services/database_management.service'; import { AdminOperationLogService } from '../services/admin_operation_log.service'; import { AdminOperationLogInterceptor } from '../admin_operation_log.interceptor'; import { AdminDatabaseExceptionFilter } from '../admin_database_exception.filter'; import { AdminGuard } from '../admin.guard'; import { UserStatus } from '../../../core/db/users/user_status.enum'; describe('Admin Database Management Integration Tests', () => { let app: INestApplication; let module: TestingModule; let controller: AdminDatabaseController; let service: DatabaseManagementService; // 测试数据 const testUser = { username: 'admin-test-user', nickname: '管理员测试用户', email: 'admin-test@example.com', role: 1, status: UserStatus.ACTIVE }; const testProfile = { user_id: '1', bio: '管理员测试档案', current_map: 'test-plaza', pos_x: 100.5, pos_y: 200.3, status: 1 }; const testZulipAccount = { gameUserId: '1', zulipUserId: 12345, zulipEmail: 'test@zulip.com', zulipFullName: '测试用户', zulipApiKeyEncrypted: 'encrypted_test_key', status: 'active' }; beforeAll(async () => { module = await Test.createTestingModule({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: ['.env.test', '.env'] }) ], controllers: [AdminDatabaseController], providers: [ DatabaseManagementService, // Mock AdminOperationLogService for testing { provide: AdminOperationLogService, useValue: { createLog: jest.fn().mockResolvedValue({}), queryLogs: jest.fn().mockResolvedValue({ logs: [], total: 0 }), getLogById: jest.fn().mockResolvedValue(null), getStatistics: jest.fn().mockResolvedValue({}), cleanupExpiredLogs: jest.fn().mockResolvedValue(0), getAdminOperationHistory: jest.fn().mockResolvedValue([]), getSensitiveOperations: jest.fn().mockResolvedValue({ logs: [], total: 0 }) } }, // Mock AdminOperationLogInterceptor { provide: AdminOperationLogInterceptor, useValue: { intercept: jest.fn().mockImplementation((context, next) => next.handle()) } }, { provide: 'UsersService', useValue: { findAll: jest.fn().mockResolvedValue([]), findOne: jest.fn().mockResolvedValue({ ...testUser, id: BigInt(1) }), create: jest.fn().mockResolvedValue({ ...testUser, id: BigInt(1) }), update: jest.fn().mockResolvedValue({ ...testUser, id: BigInt(1) }), remove: jest.fn().mockResolvedValue(undefined), search: jest.fn().mockResolvedValue([]), count: jest.fn().mockResolvedValue(0) } }, { provide: 'IUserProfilesService', useValue: { findAll: jest.fn().mockResolvedValue([]), findOne: jest.fn().mockResolvedValue({ ...testProfile, id: BigInt(1) }), create: jest.fn().mockResolvedValue({ ...testProfile, id: BigInt(1) }), update: jest.fn().mockResolvedValue({ ...testProfile, id: BigInt(1) }), remove: jest.fn().mockResolvedValue(undefined), findByMap: jest.fn().mockResolvedValue([]), count: jest.fn().mockResolvedValue(0) } }, { provide: 'ZulipAccountsService', useValue: { findMany: jest.fn().mockResolvedValue({ accounts: [] }), findById: jest.fn().mockResolvedValue(testZulipAccount), create: jest.fn().mockResolvedValue({ ...testZulipAccount, id: '1' }), update: jest.fn().mockResolvedValue({ ...testZulipAccount, id: '1' }), delete: jest.fn().mockResolvedValue(undefined), getStatusStatistics: jest.fn().mockResolvedValue({ active: 0, inactive: 0, suspended: 0, error: 0, total: 0 }) } } ] }) .overrideGuard(AdminGuard) .useValue({ canActivate: () => true }) .compile(); app = module.createNestApplication(); app.useGlobalFilters(new AdminDatabaseExceptionFilter()); await app.init(); controller = module.get(AdminDatabaseController); service = module.get(DatabaseManagementService); }); afterAll(async () => { await app.close(); }); describe('用户管理功能测试', () => { it('应该成功获取用户列表', async () => { const result = await controller.getUserList(20, 0); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.items).toBeInstanceOf(Array); expect(result.data.total).toBeDefined(); expect(result.data.limit).toBe(20); expect(result.data.offset).toBe(0); expect(result.message).toBe('用户列表获取成功'); }); it('应该成功获取用户详情', async () => { const result = await controller.getUserById('1'); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.username).toBe(testUser.username); expect(result.message).toBe('用户详情获取成功'); }); it('应该成功创建用户', async () => { const result = await controller.createUser(testUser); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.username).toBe(testUser.username); expect(result.message).toBe('用户创建成功'); }); it('应该成功更新用户', async () => { const updateData = { nickname: '更新后的昵称' }; const result = await controller.updateUser('1', updateData); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.message).toBe('用户更新成功'); }); it('应该成功删除用户', async () => { const result = await controller.deleteUser('1'); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data.deleted).toBe(true); expect(result.message).toBe('用户删除成功'); }); it('应该成功搜索用户', async () => { const result = await controller.searchUsers('admin', 20); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.items).toBeInstanceOf(Array); expect(result.message).toBe('用户搜索成功'); }); }); describe('用户档案管理功能测试', () => { it('应该成功获取用户档案列表', async () => { const result = await controller.getUserProfileList(20, 0); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.items).toBeInstanceOf(Array); expect(result.message).toBe('用户档案列表获取成功'); }); it('应该成功获取用户档案详情', async () => { const result = await controller.getUserProfileById('1'); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.user_id).toBe(testProfile.user_id); expect(result.message).toBe('用户档案详情获取成功'); }); it('应该成功创建用户档案', async () => { const result = await controller.createUserProfile(testProfile); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.user_id).toBe(testProfile.user_id); expect(result.message).toBe('用户档案创建成功'); }); it('应该成功更新用户档案', async () => { const updateData = { bio: '更新后的简介' }; const result = await controller.updateUserProfile('1', updateData); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.message).toBe('用户档案更新成功'); }); it('应该成功删除用户档案', async () => { const result = await controller.deleteUserProfile('1'); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data.deleted).toBe(true); expect(result.message).toBe('用户档案删除成功'); }); it('应该成功根据地图获取用户档案', async () => { const result = await controller.getUserProfilesByMap('plaza', 20, 0); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.items).toBeInstanceOf(Array); expect(result.message).toBe('地图 plaza 的用户档案获取成功'); }); }); describe('Zulip账号关联管理功能测试', () => { it('应该成功获取Zulip账号关联列表', async () => { const result = await controller.getZulipAccountList(20, 0); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.items).toBeInstanceOf(Array); expect(result.message).toBe('Zulip账号关联列表获取成功'); }); it('应该成功获取Zulip账号关联详情', async () => { const result = await controller.getZulipAccountById('1'); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.gameUserId).toBe(testZulipAccount.gameUserId); expect(result.message).toBe('Zulip账号关联详情获取成功'); }); it('应该成功创建Zulip账号关联', async () => { const result = await controller.createZulipAccount(testZulipAccount); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.gameUserId).toBe(testZulipAccount.gameUserId); expect(result.message).toBe('Zulip账号关联创建成功'); }); it('应该成功更新Zulip账号关联', async () => { const updateData = { status: 'inactive' }; const result = await controller.updateZulipAccount('1', updateData); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.message).toBe('Zulip账号关联更新成功'); }); it('应该成功删除Zulip账号关联', async () => { const result = await controller.deleteZulipAccount('1'); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data.deleted).toBe(true); expect(result.message).toBe('Zulip账号关联删除成功'); }); it('应该成功批量更新Zulip账号状态', async () => { const batchData = { ids: ['1', '2', '3'], status: 'active' as 'active' | 'inactive' | 'suspended' | 'error', reason: '批量激活测试' }; const result = await controller.batchUpdateZulipAccountStatus(batchData); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.total).toBe(3); expect(result.message).toContain('批量更新完成'); }); it('应该成功获取Zulip账号关联统计', async () => { const result = await controller.getZulipAccountStatistics(); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.total).toBeDefined(); expect(result.message).toBe('Zulip账号关联统计获取成功'); }); }); describe('系统功能测试', () => { it('应该成功进行健康检查', async () => { const result = await controller.healthCheck(); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data.status).toBe('healthy'); expect(result.data.services).toBeDefined(); expect(result.message).toBe('数据库管理系统运行正常'); }); }); describe('响应格式一致性测试', () => { it('所有成功响应应该有统一的格式', async () => { const responses = [ await controller.getUserList(20, 0), await controller.getUserById('1'), await controller.getUserProfileList(20, 0), await controller.getZulipAccountList(20, 0), await controller.healthCheck() ]; responses.forEach(response => { expect(response).toHaveProperty('success'); expect(response).toHaveProperty('message'); expect(response).toHaveProperty('data'); expect(response).toHaveProperty('timestamp'); expect(response).toHaveProperty('request_id'); expect(response.success).toBe(true); expect(typeof response.message).toBe('string'); expect(typeof response.timestamp).toBe('string'); expect(typeof response.request_id).toBe('string'); }); }); it('列表响应应该有分页信息', async () => { const listResponses = [ await controller.getUserList(20, 0), await controller.getUserProfileList(20, 0), await controller.getZulipAccountList(20, 0) ]; listResponses.forEach(response => { expect(response.data).toHaveProperty('items'); expect(response.data).toHaveProperty('total'); expect(response.data).toHaveProperty('limit'); expect(response.data).toHaveProperty('offset'); expect(response.data).toHaveProperty('has_more'); expect(Array.isArray(response.data.items)).toBe(true); expect(typeof response.data.total).toBe('number'); expect(typeof response.data.limit).toBe('number'); expect(typeof response.data.offset).toBe('number'); expect(typeof response.data.has_more).toBe('boolean'); }); }); }); describe('参数验证测试', () => { it('应该正确处理分页参数限制', async () => { // 测试超过最大限制的情况 const result = await controller.getUserList(200, 0); expect(result).toBeDefined(); expect(result.success).toBe(true); }); it('应该正确处理搜索参数限制', async () => { const result = await controller.searchUsers('test', 100); expect(result).toBeDefined(); expect(result.success).toBe(true); }); }); });