nestjs - Nestjs / Typeorm 在每次测试后使用事务回滚数据库状态
问题描述
我正在尝试使用带有事务的 Nestjs/Typeorm 在每次 e2e 测试之前/之后启动和回滚数据库状态。
我在下面包含了一个代码片段尝试。我正在尝试覆盖 EntityManager 提供程序,以便使用 QueryRunner 实例对其进行初始化,以便我可以在每次测试之前/之后启动和回滚事务。但是,我似乎无法让存储库(请参阅下面代码片段中的 beforeEach 方法中的注释)来使用我重写的 EntityManager 实例,以启用成功的事务使用.....我认为这就是为什么事务在每个之后都没有回滚测试完成了??
let app: INestApplication;
let testModule: TestingModule;
afterEach(async () => {
const em: EntityManager = testModule.get(getEntityManagerToken('default'));
await em.queryRunner.rollbackTransaction();
});
beforeEach(async () => {
const con: Connection = testModule.get(Connection);
const em: EntityManager = testModule.get(getEntityManagerToken('default'));
const repo: CourseRepository = testModule.get(CourseRepository);
const result: boolean = repo.isEntityManagerMine(em); // false => the repo is not using the default entity manager
const conResult: boolean = repo.isConnectionMine(em.connection); // true => the repo is using the same connection
await em.queryRunner.startTransaction();
});
afterAll(async() => {
await app.close();
await testModule.close();
});
beforeAll(async () => {
testModule = await Test.createTestingModule({
imports: [AppModule],})
.overrideProvider(getEntityManagerToken('default'))
.useFactory({
factory: (connection: Connection): EntityManager => {
const queryRunner: QueryRunner = connection.createQueryRunner('master');
const entityManager: EntityManager = connection.createEntityManager(queryRunner);
return entityManager;
},
inject:[getConnectionToken('default')],
})
.compile();
app = testModule.createNestApplication();
await app.init();
});
// tests using request from supertest library
解决方案
我遇到了类似的问题:我正在使用Nestjs + TypeORM + Jest设置。我正在使用DataMapper 模式。
我想,当我们编写集成测试时,我们实际上是在数据库中插入记录。我也不想使用新的数据库,我必须在其中创建模式并为所有数据播种 - 当我的项目变得更大时,这可能会导致时间增加。使用单独的数据库进行测试的另一个威胁是,确保应用更改的顺序。一个错误的步骤可能会占用我修复种子数据的无数小时。
在运行集成测试时在 DB 中插入数据的问题是 - 对于由 repository.insert() 或 repository.save() 完成的每个插入 - typeorm 创建一个新事务并提交它。如果我[在 beforeAll() 中启动一个 txn - 运行测试 - 在 afterAll() 中回滚 txn ] ,这会产生一个问题,因为已经在存储库级别完成了提交。这使得上述流程毫无用处。
以下是我遵循的解决方案。
- 使用与开发环境相同的数据库进行集成测试
- 编写集成测试
- 在 afterAll() 块中编写删除语句
以下是代码块:
afterAll(async () => {
await queryRunner.startTransaction();
await queryRunner.query(`delete from \"Accounts\"
where \"walletWalletId\" in
(select \"wallet_id\" from \"Wallet\"
where \"userUuid\" = \'`+VALID_UUID+'\')');
await queryRunner.query(`delete from \"Wallet\"
where \"userUuid\" = \'`+ VALID_UUID+'\'');
await queryRunner.query(`delete from \"Users\"
where \"uuid\" = \'`+VALID_UUID+'\'');
await queryRunner.commitTransaction();
});
推荐阅读
- c# - 当前上下文中不存在名称“ViewH”(C#)
- python - 如何将单行维度附加到 ndarray 形状?
- javascript - 包装列表项标签带着
- 标签
- java - 使用 MaterializeCSS 和 Thymeleaf 的复选框输入
- visual-studio - 在 Visual Studio 2019 中使用 VSCode 键盘快捷键
- angular - 将身份验证令牌传递给自定义 Angular 7 库
- javascript - 使用 AJAX 验证用户时获取正确返回值的问题
- angular - Angular 日历开始日
- node.js - 我在 npm start 命令中收到错误,我该怎么办?
- c# - 如何从 ServiceLocator 迁移到依赖注入?具体例子