-
-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rollback database in e2e tests #1843
Comments
I solved it using a separate db for e2e tests. When starting e2e tests, drop the db and re-add all migrations, including a "test migration" which adds some data. For e2e tests I'm using the my whole app module, just overriding the typeorm config factory (for this to work, my normal case needs to use export class TypeormE2EConfigService implements TypeOrmOptionsFactory {
createTypeOrmOptions(): PostgresConnectionOptions {
return {
... my usual local DB connection options
// Use a separate database, where data can be safely dropped each time
database: 'test',
// We want a clean database state, but need some of the dev data to test swaps
dropSchema: true,
synchronize: false,
migrationsRun: true,
migrations: [
'src/models/migrations/*.ts',
'src/models/testMigrations/*.ts',
],
};
}
}
...
// test app initialization
const moduleFixture = await Test
.createTestingModule({ imports: [AppModule] })
.overrideProvider(TypeormConfigService) // <- this is my "regular" typeorm options factory
.useValue(typeormOptionsFactory)
.compile(); |
Maybe this helps you? |
Thanks! But both your comments is near to reload your seeding data and restart database in each test case even inside one test file. When I run each my test file in beforeAll part, I just use my orm configurations which depends on test env - it always start my database with get dbParams(): TypeOrmModuleAsyncOptions {
const SOURCE_PATH = process.env.NODE_ENV === 'production' ? 'dist' : 'src';
return {
type: 'postgres',
host: this.envConfig.db.host,
port: this.envConfig.db.port,
username: this.envConfig.db.user,
password: this.envConfig.db.password,
database: this.envConfig.db.name,
synchronize: process.env.NODE_ENV === 'test',
dropSchema: process.env.NODE_ENV === 'test',
entities: [`${SOURCE_PATH}/**/**.entity{.ts,.js}`],
} as TypeOrmModuleAsyncOptions;
} It lets me reload my test data each time. As I've seen you seed data using test migration or using test fixtures. But my question was about using rollback transaction in every test inside file. Somehow I should give to my app module in tests database which have been started with queryRunner. After each I roll it back: beforeAll(() => {
// Here I start my app with testing data and database with startTransaction()
})
afterEach(async () => {
await database.rollbackTransaction();
})
it('Should update', async () => {
await request(app.getHttpServer())
.post('/users')
// some data to set
.expect(201);
expect(await userService.findAll()).toEqual(//some result);
});
it('Should update again', async () => {
await request(app.getHttpServer())
.post('/users')
// some another data to set
.expect(201);
expect(await userService.findAll()).toEqual(//some result without data from test before);
}); In all this tests I don't have to restart all my service and database, I just rollback transactions. |
Please, use StackOverflow for such questions. |
I would like to share with you my workaround for this problem. It is not very clean but it works (in my case). As long as we don't have any built-in option, using below code you are able to rollback all MySQL transactions with db changes that were created during e2e tests. let app: INestApplication;
let fixture: TestingModule;
let queryRunner: QueryRunner;
beforeAll(async () => {
fixture = await Test.createTestingModule({
imports: [AppModule],
})
.compile();
app = fixture.createNestApplication();
app.useGlobalPipes(new ValidationPipe());
await app.init();
const dbConnection = fixture.get(Connection);
const manager = fixture.get(EntityManager);
// @ts-ignore
queryRunner = manager.queryRunner = dbConnection.createQueryRunner('master');
});
beforeEach(async () => {
await queryRunner.startTransaction();
});
afterEach(async () => {
await queryRunner.rollbackTransaction();
});
it('should create new email address subscription', () => {
return request(app.getHttpServer())
.post(URL)
.send({email: 'john.doe@owwly.com'})
.expect(201);
}); |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I'm submitting a...
Current behavior
All database should be cleaned, reloaded and seed before each e2e test. If have many tests you spend too much time.
Expected behavior
Each test with database is never committed, all data becomes as initial after each. Database creates and seed only ones before all tests.
Minimal reproduction of the problem with instructions
What is the motivation / use case for changing the behavior?
Some other frameworks have good practice to roll back all DB transactions inside test case after each test is finished. It lets you not to spend too much time for clean and reload all your DB and seed testing fixtures. You just load your test database, seed data before all tests and clean it after finish optionally but all your tests are independent and have the same environment.
I can't find it in docs or issues, even DB transactions at least. Maybe you have something for Typeorm?
Environment
The text was updated successfully, but these errors were encountered: