如何配置TypeORM使其同时支持应用运行与测试环境的数据库操作
问题根源
你当前报错的核心原因是项目入口未主动调用连接初始化方法,修改后的连接工具不会自动创建default连接,同时原有实现存在重复创建报错、清理逻辑异步等待异常的问题,调整方案如下:
步骤1:优化TypeORM连接工具
增加连接存在性判断、环境适配逻辑,修复清理方法的异步问题:
import { createConnection, getConnection, hasConnection, getConnectionOptions } from 'typeorm'; const connection = { async create(overrideConfig: Record<string, any> = {}){ // 避免重复创建连接报错 if(hasConnection('default')) { return getConnection('default'); } const defaultOptions = await getConnectionOptions(); return createConnection({ ...defaultOptions, // 按环境自动切换数据库host,测试环境默认使用本地数据库,可自行调整 host: process.env.NODE_ENV === 'test' ? 'localhost' : 'database_clina', ...overrideConfig }); }, async close(){ if(hasConnection('default')) { await getConnection().close(); } }, async clear(){ const connection = getConnection(); const entities = connection.entityMetadatas; // 等待所有表清理完成,同时处理外键约束导致的删除失败问题 await Promise.all(entities.map(async (entity) => { const repository = connection.getRepository(entity.name); await repository.query(`SET FOREIGN_KEY_CHECKS = 0;`); await repository.query(`DELETE FROM ${entity.tableName}`); await repository.query(`SET FOREIGN_KEY_CHECKS = 1;`); })); }, }; export default connection;
步骤2:修改项目入口文件
区分环境初始化连接,测试场景下交由测试用例手动控制连接生命周期:
import "reflect-metadata"; import connection from "./infra/typeorm"; import express from "express"; import { usersRoutes } from "./routes/users.routes"; const app = express(); app.use(express.json()); app.use("/users", usersRoutes); // 非测试环境自动初始化连接并启动服务 if(process.env.NODE_ENV !== 'test') { (async () => { try { await connection.create(); app.listen(3000, () => { console.log('服务已启动,监听端口3000'); }) } catch (err) { console.error('数据库连接失败:', err); process.exit(1); } })() } export { app };
步骤3:配置环境变量与测试用例
- 在
package.json中区分不同环境的启动参数:
{ "scripts": { "dev": "NODE_ENV=development ts-node src/index.ts", "start": "NODE_ENV=production node dist/index.js", "test": "NODE_ENV=test jest" } }
- 测试用例示例(以Jest为例):
import { app } from '../src/index'; import connection from '../src/infra/typeorm'; import request from 'supertest'; // 所有测试执行前初始化测试数据库连接 beforeAll(async () => { await connection.create({ // 可传入测试数据库专属配置,比如使用独立的测试库避免污染开发数据 database: 'your_test_database_name' }); }) // 单条测试执行前清空数据库,保证测试用例隔离 beforeEach(async () => { await connection.clear(); }) // 所有测试执行完成后关闭连接 afterAll(async () => { await connection.close(); }) // 测试用例示例 test('用户创建接口正常返回', async () => { const res = await request(app) .post('/users') .send({ name: '测试用户', email: 'test@example.com' }); expect(res.statusCode).toBe(201); })
调整完成后,开发/生产环境启动时会自动创建数据库连接,支持Insomnia接口调用;测试场景下可手动控制连接的创建、清理、关闭逻辑,两端互不冲突。
内容的提问来源于stack exchange,提问作者Vagner Wentz
相关产品推荐
相关产品推荐

