import { OpenAPIHono } from '@hono/zod-openapi'; import { testClient } from 'hono/testing'; 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: ReturnType>; dataSource: DataSource | null; } /** * 创建集成测试应用实例 */ export async function createIntegrationTestApp( routes: any[], options: IntegrationTestOptions = {} ): Promise { // 使用主API应用,确保所有路由已注册 return apiApp; } /** * 创建集成测试客户端(使用hono/testing的testClient) */ export function createIntegrationTestClient( app: OpenAPIHono, options: IntegrationTestOptions = {} ): ReturnType> { const client = testClient(app); // 设置默认认证头(如果需要) if (options.setupAuth !== false) { // testClient会自动处理header,这里不需要额外设置 } 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(); } /** * 测试数据工厂函数 * 使用integration-test-db.ts中的TestDataFactory */ export { TestDataFactory } from './integration-test-db'; /** * 集成测试断言工具 */ export class IntegrationTestAssertions { /** * 断言响应状态码 */ static expectStatus(response: { status: number }, expectedStatus: number): void { if (response.status !== expectedStatus) { throw new Error(`Expected status ${expectedStatus}, but got ${response.status}`); } } /** * 断言响应包含特定字段 */ static expectResponseToHave(response: { data: any }, expectedFields: Record): void { for (const [key, value] of Object.entries(expectedFields)) { if (response.data[key] !== value) { throw new Error(`Expected field ${key} to be ${value}, but got ${response.data[key]}`); } } } /** * 断言响应包含特定结构 */ static expectResponseStructure(response: { data: 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(); }); }