简体   繁体   中英

Jest/TypeORM purge database after all tests

I would like to delete all entries into my database after or before all jest tests.

Here is my setup.js:

import { getConnection, getConnectionManager } from "typeorm"

beforeAll(async () => {
    const connectionManager = getConnectionManager()
    const connection = connectionManager.create({
        "type": "postgres",
        "host": "localhost",
        "port": 54320,
        "username": "test",
        "password": "test",
        "database": "test",
        "entities": ["../src/entities/*.ts"],
        "logging": false,
        "synchronize": true
    })
    await connection.connect()
})

afterAll(async () => {
    await getConnection().close()
})

I read on the typeorm documentation that the "synchronize" option would override the old tables with new one which are empty but it doesn't seems to work.

Here is the test I made:

describe('POST /create', () => {
    it('Create a user', async () => {
        const user: IStringTMap<string> = {
            firstName: 'John',
            lastName: 'Doe',
            email: 'john.doe@test.com',
            password: 'test123!',
        }

        const res: Response = await request(app)
            .post('/create')
            .send(user)
            .expect(200)

        expect(res.type).toEqual('application/json')
        expect(res.body.email).toBe('john.doe@test.com')
        expect(res.body.password).toBe(undefined)
    })
})

First yarn test works but the next one doesn't (email already exists)

Any idea?

Maybe a little late but was searching for this as well, this is what I came up with.

This will only delete the content inside the entities, not the entities itself.

afterEach(async () => {

    // Fetch all the entities
    const entities = getConnection().entityMetadatas;

    for (const entity of entities) {
        const repository = getConnection().getRepository(entity.name); // Get repository
        await repository.clear(); // Clear each entity table's content
    }
});

EDIT: If you're using foreign keys , make sure to add the {onDelete: "CASCADE"} property to your columns in order to delete all the records correctly.

More information about that can be found here: https://github.com/typeorm/typeorm/issues/1460#issuecomment-366982161

you can setup a new database in your e2e test file with a separate name and set the dropSchema: true option when you import the typeorm module. you can import the typeorm module int he imports the same way you do in AppModule

Sorry I do not have enough reputation to respond to Michiel's comment but,

if you are using a postgreSQL database and your table have foreign key constraints your code may not work because according to the postgreSQL documentation TRUNCATE does not fire an ON DELETE trigger

The TRUNCATE TABLE does not fire ON DELETE trigger. Instead, it fires the BEFORE TRUNCATE and AFTER TRUNCATE triggers.

So you will probably have to use the EntityManager to make an SQL query like this:

entityManager.query('TRUNCATE TABLE table_name CASCADE;')

Hope you find this helpful.

You may not have to purge the database for this test. You could alternatively use a library like faker and bypass the email duplicate validation. Faker will produce a unique user with every test run. Change your user to:


import fake from 'faker';

const user: IStringTMap<string> = {
  firstName: faker.name.firstName(),
  lastName: faker.name.lastName(),
  email: faker.internet.email(),
  password: faker.internet.password()
}

Here is a fast and efficient way to fully clean a DB with typeorm, in creating a dedicated TestService which TRUNCATE all entities in one command:

 import { Inject, Injectable } from "@nestjs/common"; import { Connection } from "typeorm"; @Injectable() export class TestService { constructor(@Inject("Connection") public connection: Connection) {} public async cleanDatabase(): Promise<void> { try { const entities = this.connection.entityMetadatas; const tableNames = entities.reduce((prev, current, index) => { return index === entities.length - 1? prev + `"${current.tableName}"`: prev + `"${current.tableName}", `; }, ""); await this.connection.query(`TRUNCATE ${tableNames} CASCADE;`); console.log("[TEST DATABASE]: Clean"); } catch (error) { throw new Error(`ERROR: Cleaning test database: ${error}`); } } }

Then you can call this function in your testing files:

 beforeEach(async () => { await testService.cleanDatabase(); });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM