| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- 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<OpenAPIHono> {
- // 使用主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<IntegrationTestContext> {
- 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<void> {
- await IntegrationTestDatabase.clearAllData();
- await IntegrationTestDatabase.cleanup();
- }
- /**
- * 测试数据工厂函数
- */
- export class TestDataFactory {
- /**
- * 创建测试用户
- */
- static async createTestUser(userData: Partial<UserEntity> = {}): Promise<UserEntity> {
- const dataSource = IntegrationTestDatabase.getDataSource();
- if (!dataSource) {
- throw new Error('Database not initialized');
- }
- const userRepository = dataSource.getRepository(UserEntity);
- const defaultUser: Partial<UserEntity> = {
- 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<UserEntity> = {}): Promise<UserEntity> {
- 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<UserEntity> = {
- 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<Role> = {}): Promise<Role> {
- const dataSource = IntegrationTestDatabase.getDataSource();
- if (!dataSource) {
- throw new Error('Database not initialized');
- }
- const roleRepository = dataSource.getRepository(Role);
- const defaultRole: Partial<Role> = {
- name: `role_${Date.now()}`,
- description: 'Test Role',
- ...roleData
- };
- const role = roleRepository.create(defaultRole);
- return await roleRepository.save(role);
- }
- /**
- * 清空所有测试数据
- */
- static async clearAllTestData(): Promise<void> {
- 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<string, any>): 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<string, any>): 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<void> {
- 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<void> {
- 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();
- });
- }
|