【问题标题】:Nestjs / Typeorm rollback database state using transaction after each testNestjs / Typeorm 在每次测试后使用事务回滚数据库状态
【发布时间】:2019-09-10 15:04:20
【问题描述】:

我正在尝试使用带有事务的 Nestjs/Typeorm 在每次 e2e 测试之前/之后启动和回滚数据库状态。

我在下面包含了一个代码 sn-p 尝试。我正在尝试覆盖 EntityManager 提供程序,以便使用 QueryRunner 实例对其进行初始化,以便我可以在每次测试之前/之后启动和回滚事务。但是,我似乎无法获取存储库(请参阅下面代码 sn-p 中 beforeEach 方法中的 cmets)来使用我覆盖的 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

【问题讨论】:

  • 但是你肯定想要测试运行之前的状态,所以擦除数据库不是一个选项?!
  • 可能不得不走那条路......虽然为了性能更愿意回滚事务,但令人费解的是为什么存储库不使用来自提供者的 EntityManager 实例......
  • 我使用await getConnection().synchronize(true); 删除数据库,这对于我的目的来说足够快。也许试试看,如果你没有明显的性能损失,那就足够了
  • 谢谢@KimKern,可能要试一试...

标签: nestjs typeform


【解决方案1】:

我遇到了类似的问题: 我正在使用 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();
});

【讨论】:

    猜你喜欢
    • 2019-05-09
    • 2018-07-21
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-06-13
    • 2012-12-29
    • 1970-01-01
    相关资源
    最近更新 更多