简体   繁体   English

在所有测试后 Jest/TypeORM 清除数据库

[英]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:这是我的 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.我在 typeorm 文档中读到“同步”选项会用新的空表覆盖旧表,但它似乎不起作用。

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)第一个yarn test有效,但下一个无效(电子邮件已存在)

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.编辑:如果您使用外键,请确保将{onDelete: "CASCADE"}属性添加到您的列中,以便正确删除所有记录。

More information about that can be found here: https://github.com/typeorm/typeorm/issues/1460#issuecomment-366982161更多信息可以在这里找到: 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.您可以在您的 e2e 测试文件中使用单独的名称设置一个新数据库,并在导入 typeorm 模块时设置dropSchema: true选项。 you can import the typeorm module int he imports the same way you do in AppModule您可以像在 AppModule 中一样导入 typeorm 模块

Sorry I do not have enough reputation to respond to Michiel's comment but,抱歉,我没有足够的声誉来回应 Michiel 的评论,但是,

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如果您使用的是 postgreSQL 数据库并且您的表有外键约束,您的代码可能无法工作,因为根据postgreSQL 文档TRUNCATE 不会触发 ON DELETE 触发器

The TRUNCATE TABLE does not fire ON DELETE trigger. TRUNCATE TABLE 不会触发 ON DELETE 触发器。 Instead, it fires the BEFORE TRUNCATE and AFTER TRUNCATE triggers.相反,它会触发 BEFORE TRUNCATE 和 AFTER TRUNCATE 触发器。

So you will probably have to use the EntityManager to make an SQL query like this:因此,您可能必须使用EntityManager进行 SQL 查询,如下所示:

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的库并绕过 email 重复验证。 Faker will produce a unique user with every test run. Faker 将在每次测试运行时产生一个唯一的用户。 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:这是使用 typeorm 完全清理数据库的一种快速有效的方法,它创建一个专用的 TestService,它在一个命令中截断所有实体:

 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:然后你可以在你的测试文件中调用这个 function :

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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