integration-test-utils.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { OpenAPIHono } from '@hono/zod-openapi';
  2. import { testClient } from 'hono/testing';
  3. import { IntegrationTestDatabase } from './integration-test-db';
  4. import { DataSource } from 'typeorm';
  5. import { UserEntity } from '../modules/users/user.entity';
  6. import { Role } from '../modules/users/role.entity';
  7. import apiApp from '../api';
  8. // /**
  9. // * 集成测试配置选项
  10. // */
  11. // export interface IntegrationTestOptions {
  12. // setupDatabase?: boolean;
  13. // setupAuth?: boolean;
  14. // setupMiddlewares?: boolean;
  15. // }
  16. // /**
  17. // * 集成测试上下文
  18. // */
  19. // export interface IntegrationTestContext {
  20. // app: OpenAPIHono;
  21. // client: ReturnType<typeof testClient<typeof apiApp>>;
  22. // dataSource: DataSource | null;
  23. // }
  24. // // /**
  25. // // * 创建集成测试应用实例
  26. // // */
  27. // // export async function createIntegrationTestApp(
  28. // // routes: any[],
  29. // // options: IntegrationTestOptions = {}
  30. // // ): Promise<OpenAPIHono> {
  31. // // // 使用主API应用,确保所有路由已注册
  32. // // return apiApp;
  33. // // }
  34. // /**
  35. // * 创建集成测试客户端(使用hono/testing的testClient)
  36. // */
  37. // export function createIntegrationTestClient(
  38. // app: OpenAPIHono,
  39. // options: IntegrationTestOptions = {}
  40. // ): ReturnType<typeof testClient<typeof apiApp>> {
  41. // const client = testClient(app);
  42. // // 设置默认认证头(如果需要)
  43. // if (options.setupAuth !== false) {
  44. // // testClient会自动处理header,这里不需要额外设置
  45. // }
  46. // return client;
  47. // }
  48. // /**
  49. // * 设置集成测试环境
  50. // */
  51. // export async function setupIntegrationTestEnvironment(
  52. // routes: any[],
  53. // options: IntegrationTestOptions = {}
  54. // ): Promise<IntegrationTestContext> {
  55. // const {
  56. // setupDatabase = true,
  57. // setupAuth = true,
  58. // setupMiddlewares = true
  59. // } = options;
  60. // // 创建测试应用
  61. // // const app = await createIntegrationTestApp(routes, options);
  62. // // 初始化数据库(如果需要)
  63. // let dataSource: DataSource | null = null;
  64. // if (setupDatabase) {
  65. // dataSource = await IntegrationTestDatabase.initialize();
  66. // }
  67. // // 创建API客户端
  68. // const client = createIntegrationTestClient(app, { setupAuth });
  69. // return {
  70. // app,
  71. // client,
  72. // dataSource
  73. // };
  74. // }
  75. // /**
  76. // * 清理集成测试环境
  77. // */
  78. // export async function cleanupIntegrationTestEnvironment(): Promise<void> {
  79. // await IntegrationTestDatabase.clearAllData();
  80. // await IntegrationTestDatabase.cleanup();
  81. // }
  82. // /**
  83. // * 测试数据工厂函数
  84. // * 使用integration-test-db.ts中的TestDataFactory
  85. // */
  86. // export { TestDataFactory } from './integration-test-db';
  87. /**
  88. * 集成测试断言工具
  89. */
  90. export class IntegrationTestAssertions {
  91. /**
  92. * 断言响应状态码
  93. */
  94. static expectStatus(response: { status: number }, expectedStatus: number): void {
  95. if (response.status !== expectedStatus) {
  96. throw new Error(`Expected status ${expectedStatus}, but got ${response.status}`);
  97. }
  98. }
  99. /**
  100. * 断言响应包含特定字段
  101. */
  102. static expectResponseToHave(response: { data: any }, expectedFields: Record<string, any>): void {
  103. for (const [key, value] of Object.entries(expectedFields)) {
  104. if (response.data[key] !== value) {
  105. throw new Error(`Expected field ${key} to be ${value}, but got ${response.data[key]}`);
  106. }
  107. }
  108. }
  109. /**
  110. * 断言响应包含特定结构
  111. */
  112. static expectResponseStructure(response: { data: any }, structure: Record<string, any>): void {
  113. for (const key of Object.keys(structure)) {
  114. if (!(key in response.data)) {
  115. throw new Error(`Expected response to have key: ${key}`);
  116. }
  117. }
  118. }
  119. /**
  120. * 断言用户存在于数据库中
  121. */
  122. static async expectUserToExist(username: string): Promise<void> {
  123. const dataSource = await IntegrationTestDatabase.getDataSource();
  124. if (!dataSource) {
  125. throw new Error('Database not initialized');
  126. }
  127. const userRepository = dataSource.getRepository(UserEntity);
  128. const user = await userRepository.findOne({ where: { username } });
  129. if (!user) {
  130. throw new Error(`Expected user ${username} to exist in database`);
  131. }
  132. }
  133. /**
  134. * 断言用户不存在于数据库中
  135. */
  136. static async expectUserNotToExist(username: string): Promise<void> {
  137. const dataSource = await IntegrationTestDatabase.getDataSource();
  138. if (!dataSource) {
  139. throw new Error('Database not initialized');
  140. }
  141. const userRepository = dataSource.getRepository(UserEntity);
  142. const user = await userRepository.findOne({ where: { username } });
  143. if (user) {
  144. throw new Error(`Expected user ${username} not to exist in database`);
  145. }
  146. }
  147. }
  148. // /**
  149. // * 集成测试生命周期钩子
  150. // */
  151. // export function setupIntegrationTestHooks() {
  152. // beforeEach(async () => {
  153. // await IntegrationTestDatabase.initialize();
  154. // });
  155. // afterEach(async () => {
  156. // await IntegrationTestDatabase.clearAllData();
  157. // });
  158. // afterAll(async () => {
  159. // await IntegrationTestDatabase.cleanup();
  160. // });
  161. // }