integration-test-db.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { DataSource } from 'typeorm';
  2. import { beforeEach, afterEach } from 'vitest';
  3. import { UserEntity } from '@/server/modules/users/user.entity';
  4. import { Role } from '@/server/modules/users/role.entity';
  5. import { ActivityEntity, ActivityType } from '@/server/modules/activities/activity.entity';
  6. import { RouteEntity } from '@/server/modules/routes/route.entity';
  7. import { VehicleType } from '@/server/modules/routes/route.schema';
  8. import { AppDataSource } from '@/server/data-source';
  9. /**
  10. * 集成测试数据库工具类 - 使用真实PostgreSQL数据库
  11. */
  12. export class IntegrationTestDatabase {
  13. /**
  14. * 清理集成测试数据库
  15. */
  16. static async cleanup(): Promise<void> {
  17. if (AppDataSource.isInitialized) {
  18. await AppDataSource.destroy();
  19. }
  20. }
  21. /**
  22. * 获取当前数据源
  23. */
  24. static async getDataSource(): Promise<DataSource> {
  25. if(!AppDataSource.isInitialized) {
  26. await AppDataSource.initialize();
  27. }
  28. return AppDataSource
  29. }
  30. }
  31. /**
  32. * 测试数据工厂类
  33. */
  34. export class TestDataFactory {
  35. /**
  36. * 创建测试用户数据
  37. */
  38. static createUserData(overrides: Partial<UserEntity> = {}): Partial<UserEntity> {
  39. const timestamp = Date.now();
  40. return {
  41. username: `testuser_${timestamp}`,
  42. password: 'TestPassword123!',
  43. email: `test_${timestamp}@example.com`,
  44. phone: `138${timestamp.toString().slice(-8)}`,
  45. nickname: `Test User ${timestamp}`,
  46. name: `Test Name ${timestamp}`,
  47. isDisabled: 0,
  48. isDeleted: 0,
  49. ...overrides
  50. };
  51. }
  52. /**
  53. * 创建测试角色数据
  54. */
  55. static createRoleData(overrides: Partial<Role> = {}): Partial<Role> {
  56. const timestamp = Date.now();
  57. return {
  58. name: `test_role_${timestamp}`,
  59. description: `Test role description ${timestamp}`,
  60. ...overrides
  61. };
  62. }
  63. /**
  64. * 在数据库中创建测试用户
  65. */
  66. static async createTestUser(dataSource: DataSource, overrides: Partial<UserEntity> = {}): Promise<UserEntity> {
  67. const userData = this.createUserData(overrides);
  68. const userRepository = dataSource.getRepository(UserEntity);
  69. const user = userRepository.create(userData);
  70. return await userRepository.save(user);
  71. }
  72. /**
  73. * 在数据库中创建测试角色
  74. */
  75. static async createTestRole(dataSource: DataSource, overrides: Partial<Role> = {}): Promise<Role> {
  76. const roleData = this.createRoleData(overrides);
  77. const roleRepository = dataSource.getRepository(Role);
  78. const role = roleRepository.create(roleData);
  79. return await roleRepository.save(role);
  80. }
  81. /**
  82. * 创建测试活动数据
  83. */
  84. static createActivityData(overrides: Partial<ActivityEntity> = {}): Partial<ActivityEntity> {
  85. const timestamp = Date.now();
  86. const now = new Date();
  87. const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
  88. return {
  89. name: `测试活动_${timestamp}`,
  90. description: `测试活动描述_${timestamp}`,
  91. type: ActivityType.DEPARTURE,
  92. startDate: now,
  93. endDate: tomorrow,
  94. venueLocationId: 1, // 默认举办地点ID
  95. isDisabled: 0,
  96. isDeleted: 0,
  97. ...overrides
  98. };
  99. }
  100. /**
  101. * 创建测试路线数据
  102. */
  103. static createRouteData(overrides: Partial<RouteEntity> = {}): Partial<RouteEntity> {
  104. const timestamp = Date.now();
  105. const now = new Date();
  106. const departureTime = new Date(now.getTime() + 2 * 60 * 60 * 1000); // 2小时后
  107. return {
  108. name: `测试路线_${timestamp}`,
  109. startLocationId: 1,
  110. endLocationId: 2,
  111. pickupPoint: `上车点_${timestamp}`,
  112. dropoffPoint: `下车点_${timestamp}`,
  113. departureTime: departureTime,
  114. vehicleType: VehicleType.BUS,
  115. price: 100,
  116. seatCount: 40,
  117. availableSeats: 40,
  118. isDisabled: 0,
  119. isDeleted: 0,
  120. ...overrides
  121. };
  122. }
  123. /**
  124. * 在数据库中创建测试活动
  125. */
  126. static async createTestActivity(dataSource: DataSource, overrides: Partial<ActivityEntity> = {}): Promise<ActivityEntity> {
  127. const activityData = this.createActivityData(overrides);
  128. const activityRepository = dataSource.getRepository(ActivityEntity);
  129. const activity = activityRepository.create(activityData);
  130. return await activityRepository.save(activity);
  131. }
  132. /**
  133. * 在数据库中创建测试路线
  134. */
  135. static async createTestRoute(dataSource: DataSource, overrides: Partial<RouteEntity> = {}): Promise<RouteEntity> {
  136. const routeData = this.createRouteData(overrides);
  137. const routeRepository = dataSource.getRepository(RouteEntity);
  138. // 如果没有提供activityId,自动创建一个测试活动
  139. if (!routeData.activityId) {
  140. const testActivity = await this.createTestActivity(dataSource);
  141. routeData.activityId = testActivity.id;
  142. }
  143. const route = routeRepository.create(routeData);
  144. return await routeRepository.save(route);
  145. }
  146. }
  147. /**
  148. * 集成测试数据库生命周期钩子
  149. */
  150. export function setupIntegrationDatabaseHooks() {
  151. beforeEach(async () => {
  152. await IntegrationTestDatabase.getDataSource();
  153. });
  154. afterEach(async () => {
  155. await IntegrationTestDatabase.cleanup();
  156. });
  157. }