我想编写这样一个单元测试文件,每次运行它时,我都会运行整个应用程序的一个实例。这部分确保了这一点:
module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
然后我想在每次单元测试后清理数据库。 ChatGPT 让我得出的结论是我应该使用交易。它建议我应该使用:
beforeEach(async () => {
await dataSource.query('BEGIN');
});
afterEach(async () => {
await dataSource.query('ROLLBACK');
});
但它不想为我工作。
然后跟聊了一番之后,我得出的结论是我应该使用
queryRunner.startTransaction()
和queryRunner.rollbackTransaction()
。但它仍然不想为我工作。
请帮我修复以下代码。
import { Test, TestingModule } from '@nestjs/testing';
import { UsersService } from './users.service';
import { AppModule } from '../../app.module';
import { DataSource, QueryRunner } from 'typeorm';
import { DATA_SOURCE } from '../database/database.providers';
import { runSeeders } from 'typeorm-extension';
import { ConfigService } from '@nestjs/config';
describe('UsersService', () => {
let service: UsersService;
let module: TestingModule;
let dataSource: DataSource;
let queryRunner: QueryRunner;
let config: ConfigService;
let createQueryRunner;
let release;
beforeAll(async () => {
module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
config = module.get<ConfigService>(ConfigService);
dataSource = module.get<DataSource>(DATA_SOURCE);
if (config.get<string>('NODE_ENV') === 'testing') {
console.info('Running seeders for testing environment');
await runSeeders(dataSource);
}
service = module.get<UsersService>(UsersService);
});
beforeEach(async () => {
queryRunner = dataSource.createQueryRunner();
await queryRunner.startTransaction();
});
afterEach(async () => {
await queryRunner.rollbackTransaction();
await queryRunner.release();
});
afterAll(async () => {
await module.close();
});
it('should be defined', async () => {
await service.create({ firstName: 'FN', lastName: 'LN', email: '[email protected]' });
await service.create({ firstName: 'FN2', lastName: 'LN2', email: '[email protected]' });
expect(service).toBeDefined();
});
it('should return a user', async () => {
const user = await service.findOneByEmail('[email protected]');
expect(user).toBeDefined();
});
});
通过一些尝试和错误,我找到了这个解决方案。我使用
<<==
注释来突出显示添加到上一个示例中的行。
import { Test, TestingModule } from '@nestjs/testing';
import { UsersService } from './users.service';
import { AppModule } from '../../app.module';
import { DataSource, QueryRunner } from 'typeorm';
import { DATA_SOURCE } from '../database/database.providers';
import { runSeeders } from 'typeorm-extension';
import { ConfigService } from '@nestjs/config';
describe('UsersService', () => {
let service: UsersService;
let module: TestingModule;
let dataSource: DataSource;
let queryRunner: QueryRunner;
let config: ConfigService;
let createQueryRunner;
let release;
beforeAll(async () => {
module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
config = module.get<ConfigService>(ConfigService);
dataSource = module.get<DataSource>(DATA_SOURCE);
if (config.get<string>('NODE_ENV') === 'testing') {
console.info('Running seeders for testing environment');
await runSeeders(dataSource);
}
service = module.get<UsersService>(UsersService);
});
beforeEach(async () => {
queryRunner = dataSource.createQueryRunner();
await queryRunner.startTransaction();
createQueryRunner = dataSource.createQueryRunner; // <<==
release = queryRunner.release; // <<==
dataSource.createQueryRunner = () => queryRunner; // <<==
queryRunner.release = () => Promise.resolve(); // <<==
});
afterEach(async () => {
await queryRunner.rollbackTransaction();
dataSource.createQueryRunner = createQueryRunner; // <<==
queryRunner.release = release; // <<==
await queryRunner.release();
});
afterAll(async () => {
await module.close();
});
it('should be defined', async () => {
await service.create({ firstName: 'FN', lastName: 'LN', email: '[email protected]' });
await service.create({ firstName: 'FN2', lastName: 'LN2', email: '[email protected]' });
expect(service).toBeDefined();
});
it('should return a user', async () => {
const user = await service.findOneByEmail('[email protected]');
expect(user).toBeDefined();
});
});
说明:
我想几乎每次对数据库进行查询时,我们都会使用
dataSource.createQueryRunner().query(<SOME SQL QUERY>)
,它会创建一个新的 queryRunner。但是为了让事务在我们的测试文件中为我们工作,我们必须在每次进行查询时使用相同的queryRunner
。上面显示了我如何弄清楚如何强制执行此行为。如果有人有更好的解决方案,欢迎分享。我希望 TypeORM 中的这个问题能够尽快得到解决,或者会引入一些更好的解决方法。