import { OpenAPIHono } from '@hono/zod-openapi'; import { createApiClient, ApiClient } from './api-client'; import { IntegrationTestDatabase } from './integration-test-db'; import { DataSource } from 'typeorm'; import { UserEntity } from '../modules/users/user.entity'; import { Role } from '../modules/users/role.entity'; import apiApp from '../api'; /** * 集成测试配置选项 */ export interface IntegrationTestOptions { setupDatabase?: boolean; setupAuth?: boolean; setupMiddlewares?: boolean; } /** * 集成测试上下文 */ export interface IntegrationTestContext { app: OpenAPIHono; client: ApiClient; dataSource: DataSource | null; } /** * 创建集成测试应用实例 */ export async function createIntegrationTestApp( routes: any[], options: IntegrationTestOptions = {} ): Promise { // 使用主API应用 return apiApp; } /** * 创建集成测试客户端 */ export function createIntegrationTestClient( app: OpenAPIHono, options: IntegrationTestOptions = {} ): ApiClient { const client = createApiClient(app, { baseURL: 'http://localhost:3000/api/v1' }); // 设置默认认证头(如果需要) if (options.setupAuth !== false) { client.setAuthToken('test-integration-token'); } return client; } /** * 设置集成测试环境 */ export async function setupIntegrationTestEnvironment( routes: any[], options: IntegrationTestOptions = {} ): Promise { const { setupDatabase = true, setupAuth = true, setupMiddlewares = true } = options; // 创建测试应用 const app = await createIntegrationTestApp(routes, options); // 初始化数据库(如果需要) let dataSource: DataSource | null = null; if (setupDatabase) { dataSource = await IntegrationTestDatabase.initialize(); } // 创建API客户端 const client = createIntegrationTestClient(app, { setupAuth }); return { app, client, dataSource }; } /** * 清理集成测试环境 */ export async function cleanupIntegrationTestEnvironment(): Promise { await IntegrationTestDatabase.clearAllData(); await IntegrationTestDatabase.cleanup(); } /** * 测试数据工厂函数 */ export class TestDataFactory { /** * 创建测试用户 */ static async createTestUser(userData: Partial = {}): Promise { const dataSource = IntegrationTestDatabase.getDataSource(); if (!dataSource) { throw new Error('Database not initialized'); } const userRepository = dataSource.getRepository(UserEntity); const defaultUser: Partial = { username: `testuser_${Date.now()}`, email: `test${Date.now()}@example.com`, password: 'testpassword123', firstName: 'Test', lastName: 'User', isActive: true, ...userData }; const user = userRepository.create(defaultUser); return await userRepository.save(user); } /** * 创建测试管理员用户 */ static async createTestAdmin(userData: Partial = {}): Promise { const dataSource = IntegrationTestDatabase.getDataSource(); if (!dataSource) { throw new Error('Database not initialized'); } const userRepository = dataSource.getRepository(UserEntity); const roleRepository = dataSource.getRepository(Role); // 确保管理员角色存在 let adminRole = await roleRepository.findOne({ where: { name: 'admin' } }); if (!adminRole) { adminRole = roleRepository.create({ name: 'admin', description: 'Administrator' }); adminRole = await roleRepository.save(adminRole); } const defaultUser: Partial = { username: `admin_${Date.now()}`, email: `admin${Date.now()}@example.com`, password: 'adminpassword123', firstName: 'Admin', lastName: 'User', isActive: true, roles: [adminRole], ...userData }; const user = userRepository.create(defaultUser); return await userRepository.save(user); } /** * 创建测试角色 */ static async createTestRole(roleData: Partial = {}): Promise { const dataSource = IntegrationTestDatabase.getDataSource(); if (!dataSource) { throw new Error('Database not initialized'); } const roleRepository = dataSource.getRepository(Role); const defaultRole: Partial = { name: `role_${Date.now()}`, description: 'Test Role', ...roleData }; const role = roleRepository.create(defaultRole); return await roleRepository.save(role); } /** * 清空所有测试数据 */ static async clearAllTestData(): Promise { await IntegrationTestDatabase.clearAllData(); } } /** * 集成测试断言工具 */ export class IntegrationTestAssertions { /** * 断言响应状态码 */ static expectStatus(response: any, expectedStatus: number): void { if (response.status !== expectedStatus) { throw new Error(`Expected status ${expectedStatus}, but got ${response.status}. Response: ${JSON.stringify(response.data)}`); } } /** * 断言响应包含特定字段 */ static expectResponseToHave(response: any, expectedFields: Record): void { for (const [key, value] of Object.entries(expectedFields)) { if ((response.data as any)[key] !== value) { throw new Error(`Expected field ${key} to be ${value}, but got ${(response.data as any)[key]}`); } } } /** * 断言响应包含特定结构 */ static expectResponseStructure(response: any, structure: Record): void { for (const key of Object.keys(structure)) { if (!(key in response.data)) { throw new Error(`Expected response to have key: ${key}`); } } } /** * 断言用户存在于数据库中 */ static async expectUserToExist(username: string): Promise { const dataSource = IntegrationTestDatabase.getDataSource(); if (!dataSource) { throw new Error('Database not initialized'); } const userRepository = dataSource.getRepository(UserEntity); const user = await userRepository.findOne({ where: { username } }); if (!user) { throw new Error(`Expected user ${username} to exist in database`); } } /** * 断言用户不存在于数据库中 */ static async expectUserNotToExist(username: string): Promise { const dataSource = IntegrationTestDatabase.getDataSource(); if (!dataSource) { throw new Error('Database not initialized'); } const userRepository = dataSource.getRepository(UserEntity); const user = await userRepository.findOne({ where: { username } }); if (user) { throw new Error(`Expected user ${username} not to exist in database`); } } } /** * 集成测试生命周期钩子 */ export function setupIntegrationTestHooks() { beforeEach(async () => { await IntegrationTestDatabase.initialize(); }); afterEach(async () => { await IntegrationTestDatabase.clearAllData(); }); afterAll(async () => { await IntegrationTestDatabase.cleanup(); }); }