Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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: '[email protected]',
            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('[email protected]')
        expect(res.body.password).toBe(undefined)
    })
})

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

Any idea?

like image 651
Jason Van Malder Avatar asked Nov 09 '19 12:11

Jason Van Malder


3 Answers

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

like image 127
Michiel Avatar answered Oct 19 '22 02:10

Michiel


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

like image 25
fafa.mnzm Avatar answered Oct 19 '22 00:10

fafa.mnzm


Here is a simple 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.map((entity) => `"${entity.tableName}"`).join(", ");
      
      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();
});
like image 3
yolan PIBRAC Avatar answered Oct 19 '22 02:10

yolan PIBRAC