/** * 性能监控属性测试 * * Property 13: 性能监控准确性 * * Validates: Requirements 8.1, 8.2 * * 测试目标: * - 验证性能监控数据的准确性 * - 确保性能指标收集的完整性 * - 验证性能警告机制的有效性 * * 最近修改: * - 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 { AdminDatabaseController } from './admin_database.controller'; import { DatabaseManagementService } from './database_management.service'; import { AdminOperationLogService } from './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 '../user_mgmt/user_status.enum'; import { PropertyTestRunner, PropertyTestGenerators, PropertyTestAssertions, DEFAULT_PROPERTY_CONFIG } from './admin_property_test.base'; describe('Property Test: 性能监控功能', () => { let app: INestApplication; let module: TestingModule; let controller: AdminDatabaseController; let performanceMetrics: any[] = []; let mockUsersService: any; let mockUserProfilesService: any; let mockZulipAccountsService: any; beforeAll(async () => { performanceMetrics = []; // 创建性能监控mock const createPerformanceAwareMock = (serviceName: string, methodName: string, baseDelay: number = 50) => { return jest.fn().mockImplementation(async (...args) => { const startTime = Date.now(); // 模拟不同的执行时间 const randomDelay = baseDelay + Math.random() * 100; await new Promise(resolve => setTimeout(resolve, randomDelay)); const endTime = Date.now(); const duration = endTime - startTime; // 记录性能指标 performanceMetrics.push({ service: serviceName, method: methodName, duration, timestamp: new Date().toISOString(), args: args.length }); // 根据方法返回适当的mock数据 if (methodName === 'findAll') { return []; } else if (methodName === 'count') { return 0; } else if (methodName === 'findOne' || methodName === 'findById') { if (serviceName === 'UsersService') { return { ...PropertyTestGenerators.generateUser(), id: BigInt(1) }; } else if (serviceName === 'UserProfilesService') { return { ...PropertyTestGenerators.generateUserProfile(), id: BigInt(1) }; } else { return { ...PropertyTestGenerators.generateZulipAccount(), id: '1' }; } } else if (methodName === 'create') { if (serviceName === 'UsersService') { return { ...args[0], id: BigInt(1) }; } else if (serviceName === 'UserProfilesService') { return { ...args[0], id: BigInt(1) }; } else { return { ...args[0], id: '1' }; } } else if (methodName === 'update') { if (serviceName === 'UsersService') { return { ...PropertyTestGenerators.generateUser(), ...args[1], id: args[0] }; } else if (serviceName === 'UserProfilesService') { return { ...PropertyTestGenerators.generateUserProfile(), ...args[1], id: args[0] }; } else { return { ...PropertyTestGenerators.generateZulipAccount(), ...args[1], id: args[0] }; } } else if (methodName === 'findMany') { return { accounts: [], total: 0 }; } else if (methodName === 'getStatusStatistics') { return { active: 0, inactive: 0, suspended: 0, error: 0, total: 0 }; } return {}; }); }; mockUsersService = { findAll: createPerformanceAwareMock('UsersService', 'findAll', 30), findOne: createPerformanceAwareMock('UsersService', 'findOne', 20), create: createPerformanceAwareMock('UsersService', 'create', 80), update: createPerformanceAwareMock('UsersService', 'update', 60), remove: createPerformanceAwareMock('UsersService', 'remove', 40), search: createPerformanceAwareMock('UsersService', 'search', 100), count: createPerformanceAwareMock('UsersService', 'count', 25) }; mockUserProfilesService = { findAll: createPerformanceAwareMock('UserProfilesService', 'findAll', 35), findOne: createPerformanceAwareMock('UserProfilesService', 'findOne', 25), create: createPerformanceAwareMock('UserProfilesService', 'create', 90), update: createPerformanceAwareMock('UserProfilesService', 'update', 70), remove: createPerformanceAwareMock('UserProfilesService', 'remove', 45), findByMap: createPerformanceAwareMock('UserProfilesService', 'findByMap', 120), count: createPerformanceAwareMock('UserProfilesService', 'count', 30) }; mockZulipAccountsService = { findMany: createPerformanceAwareMock('ZulipAccountsService', 'findMany', 40), findById: createPerformanceAwareMock('ZulipAccountsService', 'findById', 30), create: createPerformanceAwareMock('ZulipAccountsService', 'create', 100), update: createPerformanceAwareMock('ZulipAccountsService', 'update', 80), delete: createPerformanceAwareMock('ZulipAccountsService', 'delete', 50), batchUpdateStatus: createPerformanceAwareMock('ZulipAccountsService', 'batchUpdateStatus', 120), getStatusStatistics: createPerformanceAwareMock('ZulipAccountsService', 'getStatusStatistics', 60) }; module = await Test.createTestingModule({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: ['.env.test', '.env'] }) ], controllers: [AdminDatabaseController], providers: [ DatabaseManagementService, { 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 }) } }, { provide: AdminOperationLogInterceptor, useValue: { intercept: jest.fn().mockImplementation((context, next) => next.handle()) } }, { provide: 'UsersService', useValue: mockUsersService }, { provide: 'IUserProfilesService', useValue: mockUserProfilesService }, { provide: 'ZulipAccountsService', useValue: mockZulipAccountsService } ] }) .overrideGuard(AdminGuard) .useValue({ canActivate: () => true }) .compile(); app = module.createNestApplication(); app.useGlobalFilters(new AdminDatabaseExceptionFilter()); await app.init(); controller = module.get(AdminDatabaseController); }); afterAll(async () => { await app.close(); }); beforeEach(() => { performanceMetrics.length = 0; // 清空性能指标 }); describe('Property 13: 性能监控准确性', () => { it('操作执行时间应该被准确记录', async () => { await PropertyTestRunner.runPropertyTest( '操作执行时间记录准确性', () => PropertyTestGenerators.generateUser(), async (userData) => { const startTime = Date.now(); // 执行操作 await controller.createUser({ ...userData, status: UserStatus.ACTIVE }); const endTime = Date.now(); const totalDuration = endTime - startTime; // 验证性能指标被记录 const createMetrics = performanceMetrics.filter(m => m.service === 'UsersService' && m.method === 'create' ); expect(createMetrics.length).toBeGreaterThan(0); const createMetric = createMetrics[0]; expect(createMetric.duration).toBeGreaterThan(0); expect(createMetric.duration).toBeLessThan(totalDuration + 50); // 允许一些误差 expect(createMetric.timestamp).toBeDefined(); // 验证时间戳格式 const timestamp = new Date(createMetric.timestamp); expect(timestamp.toISOString()).toBe(createMetric.timestamp); }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 20 } ); }); it('不同操作类型的性能指标应该被正确分类', async () => { await PropertyTestRunner.runPropertyTest( '操作类型性能分类', () => ({ user: PropertyTestGenerators.generateUser(), profile: PropertyTestGenerators.generateUserProfile(), zulipAccount: PropertyTestGenerators.generateZulipAccount() }), async ({ user, profile, zulipAccount }) => { // 执行不同类型的操作 await controller.getUserList(10, 0); await controller.createUser({ ...user, status: UserStatus.ACTIVE }); await controller.getUserProfileList(10, 0); await controller.createUserProfile(profile); await controller.getZulipAccountList(10, 0); await controller.createZulipAccount(zulipAccount); // 验证不同服务的性能指标 const userServiceMetrics = performanceMetrics.filter(m => m.service === 'UsersService'); const profileServiceMetrics = performanceMetrics.filter(m => m.service === 'UserProfilesService'); const zulipServiceMetrics = performanceMetrics.filter(m => m.service === 'ZulipAccountsService'); expect(userServiceMetrics.length).toBeGreaterThan(0); expect(profileServiceMetrics.length).toBeGreaterThan(0); expect(zulipServiceMetrics.length).toBeGreaterThan(0); // 验证方法分类 const createMethods = performanceMetrics.filter(m => m.method === 'create'); const findAllMethods = performanceMetrics.filter(m => m.method === 'findAll'); const countMethods = performanceMetrics.filter(m => m.method === 'count'); expect(createMethods.length).toBe(3); // 三个create操作 expect(findAllMethods.length).toBe(3); // 三个findAll操作 expect(countMethods.length).toBe(3); // 三个count操作 }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 } ); }); it('复杂查询的性能应该被正确监控', async () => { await PropertyTestRunner.runPropertyTest( '复杂查询性能监控', () => ({ searchTerm: PropertyTestGenerators.generateUser().username.substring(0, 3), mapName: ['plaza', 'forest', 'beach'][Math.floor(Math.random() * 3)], limit: Math.floor(Math.random() * 50) + 10, offset: Math.floor(Math.random() * 100) }), async ({ searchTerm, mapName, limit, offset }) => { // 执行复杂查询操作 await controller.searchUsers(searchTerm, limit); await controller.getUserProfilesByMap(mapName, limit, offset); await controller.getZulipAccountStatistics(); // 验证复杂查询的性能指标 const searchMetrics = performanceMetrics.filter(m => m.method === 'search'); const mapQueryMetrics = performanceMetrics.filter(m => m.method === 'findByMap'); const statsMetrics = performanceMetrics.filter(m => m.method === 'getStatusStatistics'); expect(searchMetrics.length).toBeGreaterThan(0); expect(mapQueryMetrics.length).toBeGreaterThan(0); expect(statsMetrics.length).toBeGreaterThan(0); // 验证复杂查询通常耗时更长 const searchDuration = searchMetrics[0].duration; const mapQueryDuration = mapQueryMetrics[0].duration; const statsDuration = statsMetrics[0].duration; expect(searchDuration).toBeGreaterThan(50); // 搜索操作基础延迟100ms expect(mapQueryDuration).toBeGreaterThan(70); // 地图查询基础延迟120ms expect(statsDuration).toBeGreaterThan(30); // 统计查询基础延迟60ms }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 } ); }); it('批量操作的性能应该被准确监控', async () => { await PropertyTestRunner.runPropertyTest( '批量操作性能监控', () => { const accountIds = Array.from({ length: Math.floor(Math.random() * 5) + 2 }, (_, i) => `account_${i + 1}`); const targetStatus = ['active', 'inactive', 'suspended'][Math.floor(Math.random() * 3)]; return { accountIds, targetStatus }; }, async ({ accountIds, targetStatus }) => { const startTime = Date.now(); // 执行批量操作 await controller.batchUpdateZulipAccountStatus({ ids: accountIds, status: targetStatus as any, reason: '性能测试批量更新' }); const endTime = Date.now(); const totalDuration = endTime - startTime; // 验证批量操作的性能指标 const updateMetrics = performanceMetrics.filter(m => m.service === 'ZulipAccountsService' && m.method === 'update' ); expect(updateMetrics.length).toBe(accountIds.length); // 验证每个更新操作的性能 updateMetrics.forEach(metric => { expect(metric.duration).toBeGreaterThan(0); expect(metric.duration).toBeLessThan(200); // 单个操作不应超过200ms }); // 验证总体性能合理性 const totalServiceTime = updateMetrics.reduce((sum, m) => sum + m.duration, 0); expect(totalServiceTime).toBeLessThan(totalDuration + 100); // 允许一些并发优化 }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 10 } ); }); it('性能异常应该被正确识别', async () => { await PropertyTestRunner.runPropertyTest( '性能异常识别', () => PropertyTestGenerators.generateUser(), async (userData) => { // 模拟慢查询(通过增加延迟) const originalFindOne = mockUsersService.findOne; mockUsersService.findOne = jest.fn().mockImplementation(async (...args) => { const startTime = Date.now(); // 模拟异常慢的查询 await new Promise(resolve => setTimeout(resolve, 300)); const endTime = Date.now(); const duration = endTime - startTime; performanceMetrics.push({ service: 'UsersService', method: 'findOne', duration, timestamp: new Date().toISOString(), args: args.length, slow: duration > 200 // 标记为慢查询 }); return { ...PropertyTestGenerators.generateUser(), id: BigInt(1) }; }); // 执行操作 await controller.getUserById('1'); // 恢复原始mock mockUsersService.findOne = originalFindOne; // 验证慢查询被识别 const slowQueries = performanceMetrics.filter(m => m.slow === true); expect(slowQueries.length).toBeGreaterThan(0); const slowQuery = slowQueries[0]; expect(slowQuery.duration).toBeGreaterThan(200); expect(slowQuery.service).toBe('UsersService'); expect(slowQuery.method).toBe('findOne'); }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 10 } ); }); it('并发操作的性能应该被独立监控', async () => { await PropertyTestRunner.runPropertyTest( '并发操作性能监控', () => ({ concurrentCount: Math.floor(Math.random() * 3) + 2 // 2-4个并发操作 }), async ({ concurrentCount }) => { const promises = []; const startTime = Date.now(); // 创建并发操作 for (let i = 0; i < concurrentCount; i++) { const user = PropertyTestGenerators.generateUser(); promises.push( controller.createUser({ ...user, status: UserStatus.ACTIVE, username: `${user.username}_${i}` // 确保唯一性 }) ); } // 等待所有操作完成 await Promise.all(promises); const endTime = Date.now(); const totalDuration = endTime - startTime; // 验证并发操作的性能指标 const createMetrics = performanceMetrics.filter(m => m.service === 'UsersService' && m.method === 'create' ); expect(createMetrics.length).toBe(concurrentCount); // 验证每个操作都有独立的性能记录 createMetrics.forEach((metric, index) => { expect(metric.duration).toBeGreaterThan(0); expect(metric.timestamp).toBeDefined(); // 验证时间戳在合理范围内 const metricTime = new Date(metric.timestamp).getTime(); expect(metricTime).toBeGreaterThanOrEqual(startTime); expect(metricTime).toBeLessThanOrEqual(endTime); }); // 验证并发执行的效率 const avgDuration = createMetrics.reduce((sum, m) => sum + m.duration, 0) / concurrentCount; expect(totalDuration).toBeLessThan(avgDuration * concurrentCount * 1.2); // 并发应该有一定效率提升 }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 10 } ); }); it('性能统计数据应该准确计算', async () => { await PropertyTestRunner.runPropertyTest( '性能统计准确性', () => ({ operationCount: Math.floor(Math.random() * 8) + 3 // 3-10个操作 }), async ({ operationCount }) => { // 执行多个操作 for (let i = 0; i < operationCount; i++) { await controller.getUserList(10, i * 10); } // 计算性能统计 const findAllMetrics = performanceMetrics.filter(m => m.service === 'UsersService' && m.method === 'findAll' ); expect(findAllMetrics.length).toBe(operationCount); // 计算统计数据 const durations = findAllMetrics.map(m => m.duration); const totalDuration = durations.reduce((sum, d) => sum + d, 0); const avgDuration = totalDuration / durations.length; const minDuration = Math.min(...durations); const maxDuration = Math.max(...durations); // 验证统计数据合理性 expect(totalDuration).toBeGreaterThan(0); expect(avgDuration).toBeGreaterThan(0); expect(avgDuration).toBeGreaterThanOrEqual(minDuration); expect(avgDuration).toBeLessThanOrEqual(maxDuration); expect(minDuration).toBeLessThanOrEqual(maxDuration); // 验证平均值在合理范围内(基础延迟30ms + 随机100ms) expect(avgDuration).toBeGreaterThan(20); expect(avgDuration).toBeLessThan(200); }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 } ); }); it('性能监控不应该显著影响操作性能', async () => { await PropertyTestRunner.runPropertyTest( '性能监控开销验证', () => PropertyTestGenerators.generateUser(), async (userData) => { const iterations = 5; const durations = []; // 执行多次相同操作 for (let i = 0; i < iterations; i++) { const startTime = Date.now(); await controller.createUser({ ...userData, status: UserStatus.ACTIVE, username: `${userData.username}_${i}` }); const endTime = Date.now(); durations.push(endTime - startTime); } // 验证性能一致性 const avgDuration = durations.reduce((sum, d) => sum + d, 0) / durations.length; const maxVariation = Math.max(...durations) - Math.min(...durations); // 性能变化不应该太大(监控开销应该很小) expect(maxVariation).toBeLessThan(avgDuration * 0.5); // 变化不超过平均值的50% // 验证所有操作都被监控 const createMetrics = performanceMetrics.filter(m => m.service === 'UsersService' && m.method === 'create' ); expect(createMetrics.length).toBe(iterations); }, { ...DEFAULT_PROPERTY_CONFIG, iterations: 10 } ); }); }); });