如何在NestJS与TypeORM的每个集成测试后清空数据库?
如何在每个测试后清空TypeORM数据库
针对你用TypeORMModule配置的NestJS项目,这里提供几种实用的方法来在每个测试后清空数据库:
方法1:手动遍历实体执行清空操作
在测试的afterEach钩子中,通过TypeORM的DataSource获取所有实体,执行TRUNCATE或DELETE语句清空表。适合需要精准控制清空逻辑的场景。
import { DataSource } from 'typeorm'; import { Test } from '@nestjs/testing'; import { AppModule } from './app.module'; describe('UsersModule', () => { let dataSource: DataSource; beforeEach(async () => { const moduleRef = await Test.createTestingModule({ imports: [AppModule], }).compile(); dataSource = moduleRef.get(DataSource); }); afterEach(async () => { // 获取所有已注册的实体元数据 const entities = dataSource.entityMetadatas; for (const entity of entities) { const repository = dataSource.getRepository(entity.name); // PostgreSQL中用TRUNCATE重置表并处理外键关联,适合测试场景 await repository.query(`TRUNCATE TABLE "${entity.tableName}" CASCADE;`); // 若不需要重置自增ID,可改用DELETE:await repository.delete({}); } }); // 编写你的测试用例 it('should create a user', async () => { // ...测试逻辑 }); });
方法2:通过测试模块重置实现清空
每次测试后关闭模块,下次测试重新初始化模块,结合TypeORM的synchronize: true配置(仅在测试环境启用),让TypeORM重新生成表结构,间接实现清空效果。
import { Test } from '@nestjs/testing'; import { AppModule } from './app.module'; describe('UsersModule', () => { let moduleRef: TestingModule; beforeEach(async () => { moduleRef = await Test.createTestingModule({ imports: [AppModule], }).compile(); }); afterEach(async () => { // 关闭模块,断开数据库连接 await moduleRef.close(); }); // 每次beforeEach都会重新初始化模块,synchronize: true会重建表 it('should return all users', async () => { // ...测试逻辑 }); });
方法3:利用事务回滚避免数据持久化
在每个测试开始前开启数据库事务,测试结束后回滚事务,这样测试产生的所有数据都不会写入数据库,是性能最优的方案。
import { DataSource, QueryRunner } from 'typeorm'; import { Test } from '@nestjs/testing'; import { AppModule } from './app.module'; describe('UsersModule', () => { let queryRunner: QueryRunner; beforeEach(async () => { const moduleRef = await Test.createTestingModule({ imports: [AppModule], }).compile(); const dataSource = moduleRef.get(DataSource); queryRunner = dataSource.createQueryRunner(); // 开启新事务 await queryRunner.startTransaction(); }); afterEach(async () => { // 回滚事务,丢弃所有测试数据 await queryRunner.rollbackTransaction(); await queryRunner.release(); }); it('should delete a user', async () => { // ...测试逻辑,所有数据库操作都在事务中执行 }); });
注意事项
- 务必为测试环境单独配置数据库,避免误操作开发/生产数据
- TRUNCATE语句需要根据数据库类型调整语法(如MySQL不需要CASCADE关键字)
- 事务回滚方式仅适用于支持事务的数据库,且测试中不要手动提交事务
内容的提问来源于stack exchange,提问作者cyclonejet
相关产品推荐
相关产品推荐

