Faster E2E tests & stable DB setup in NestJS
Link to earlier post on E2E tests in NestJS
The following setup allowed to cut down the duration of E2E tests by 2/3 (from 356s to 111s). The app uses TypeORM.
A single app instance for the whole E2E run.
File: test/utils/create-testing-module.ts
// Single app instance
let app: INestApplication
export async function createTestingModule() {
const moduleBuilder = Test.createTestingModule({
imports: [AppModule],
})
const module = await moduleBuilder.compile()
app = module.createNestApplication(undefined, {
logger: false,
})
await app.init()
}
export async function closeTestingModule() {
await getConnection().dropDatabase()
if (app) await app.close()
}
export function getTestingModule() {
if (!app) throw 'No app was initialized!!!'
return app
}
Functions to drop & clean up the DB:
File test/utils/clean-up-db.ts
- a collection of functions to drop/clean up the DB:
const tableNames = [
'contact',
'user',
]
export async function cleanUpDb() {
const connection = getConnection()
for (const tableName of tableNames) {
await connection.query(`DELETE FROM ${tableName};`)
}
}
export async function dropTables() {
const connection = await createConnection({
type: 'mysql',
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
})
await connection.query('SET FOREIGN_KEY_CHECKS=0;')
for (const tableName of tableNames) {
await connection.query(`DROP TABLE IF EXISTS ${tableName};`)
}
await connection.close()
}
Hooks to bootstrap the app and clean up the DB between executions:
File jest.e2e-setup.ts
- to be included to the jest configuration:
beforeAll(async () => {
await dropTables()
await createTestingModule()
})
afterAll(async () => {
await closeTestingModule()
})
beforeEach(async () => {
await cleanUpDb()
})
SQL migrations in TypeORM before a test suite
The setting is via migrationsRun
. In this way, TypeORM runs SQL migrations.
App instance for test cases
describe('TagResolver (E2E)', () => {
let app: INestApplication
let userModel: UserModel
beforeEach(async () => {
app = getTestingModule()
tagModel = app.get<TagModel>(TagModel)
})
it('verifies the app', () => {
// ...
})
})
Tweet