Jest数据库测试未与testcontainers终止。

huangapple go评论68阅读模式
英文:

Jest database test not terminating with testcontainers

问题

I am trying to test my database in my Node application (Typescript). I am using Postgres 15 and Testcontainers to test my database. My code works fine manually and my clients are being released, but for some reason my tests don't terminate.

I want to test the createUser method which uses getUserById, which also uses getTagsByUserId.

In DatabaseConnection I have a Client Pool. With getClient I return a Client from the pool.

This is my test:

import { UsersRepository } from "../../main/repository/users.repository";
import { Tag, User } from "../../main/schema/types";
import { Pool, PoolClient } from "pg";
import {
    TestContainer,
    StartedTestContainer,
    PostgreSqlContainer, Wait, StartedPostgreSqlContainer
} from "testcontainers";
import { DatabaseConnection } from "../../main/repository/DatabaseConnection";

const fs = require('fs')

jest.useFakeTimers()

const initSqlScript = fs.readFileSync('./sql/init.sql').toString()

describe('User Repository tests', () => {
    const port: number = process.env.DB_PORT ? +process.env.DB_PORT : 5432
    let pool: Pool
    let container: StartedPostgreSqlContainer

    beforeAll(async () => {
        container = await new PostgreSqlContainer("postgres:15")
            .withDatabase(process.env.POSTGRES_DB || 'test')
            .withUsername(process.env.POSTGRES_USER || 'test')
            .withPassword(process.env.POSTGRES_PASSWORD || 'test')
            .withExposedPorts(port)
            .start();
        pool = new Pool({connectionString: container.getConnectionUri()})
        const client = await pool.connect()
        await client.query(initSqlScript) // initializes my database
        await client.release()
        await DatabaseConnection.changeConnection(container.getConnectionUri()) // sets the connection for my DatabaseConnection to the test container
    })

    const userRepository = new UsersRepository()

    const originalUser: User = {
        dateOfBirth: "01-01-2000",
        email: "test",
        nickname: "test",
        password: "test",
        username: "test",
        pending: true
    }

    afterEach(async () => {
        await userRepository.clear()
    })

    it('should create a user in DB and return user with ID', async () => {
        const createdUser = await userRepository.createUser(originalUser)
        expect(createdUser.username).toBe(originalUser.username);
        expect(createdUser.email).toBe(originalUser.email);
        expect(createdUser.nickname).toBe(originalUser.nickname);
        expect(createdUser.password).toBe(originalUser.password);
        expect(createdUser.dateOfBirth).toBe(originalUser.dateOfBirth);
        expect(createdUser.pending).toBe(originalUser.pending);
        expect(typeof createdUser.userId).toBe("string")
    });
})

However, when I run my test, it does not terminate. I have checked the database and the user is created. I have also tried just returning the user object I have as input instead of getting the user from the database, but that also does not work.

I am logging any connections to my pool and it only says 1 idle connection and no active connections. When debugging, all of my clients are released.

Also, it works when I just use my local database, but I don't want that.

英文:

I am trying to test my database in my Node application (Typescript). I am using Postgres 15 and Testcontainers to test my database. My code works fine manually and my clients are being released, but for some reason my tests don't terminate.

I want to test the createUser method which uses getUserById, which also uses getTagsByUserId.

    async createUser(user: User): Promise<User> {
let client: PoolClient | undefined
try {
client = await DatabaseConnection.getClient()
await client.query('BEGIN')
const res = await client.query(this.CREATE_USER_QUERY, [user.username, user.password, user.nickname, user.email, user.dateOfBirth, user.pending])
const userId = res.rows[0].user_id
user.userId = userId
if (user.tags) {
for (const tag of user.tags) {
await client.query(this.CREATE_TAGS_QUERY, [userId, tag.toString()])
}
}
await client.query('COMMIT')
return await this.getUserById(userId)
} catch (e) {
if (client) await client.query('ROLLBACK')
throw e
} finally {
if (client) await client.release()
}
}
async getUserById(userId: string): Promise<User> {
let client: PoolClient | undefined
try {
client = await DatabaseConnection.getClient()
const res = await client.query(this.SELECT_USER_BY_ID_QUERY, [userId])
const user: User = {
dateOfBirth: res.rows[0].date_of_birth,
email: res.rows[0].email,
nickname: res.rows[0].nickname,
password: res.rows[0].password,
pending: res.rows[0].pending,
private: res.rows[0].private,
tags: [],
userId: res.rows[0].user_id,
username: res.rows[0].username
}
user.tags = await this.getTagsByUserId(userId)
return user
} catch (e) {
throw e
} finally {
if (client) await client.release()
}
}
private async getTagsByUserId(userId: string): Promise<Tag[]> {
let client: PoolClient | undefined
try {
client = await DatabaseConnection.getClient()
const res = await client.query(this.GET_TAGS_QUERY, [userId])
return res.rows.map(row => row.user_tag)
} catch (e) {
throw e
} finally {
if (client) await client.release()
}
}

In DatabaseConnection I have a Client Pool. With getClient i return a Client from the pool.

This is my test:

import {UsersRepository} from "../../main/repository/users.repository";
import {Tag, User} from "../../main/schema/types";
import {Pool, PoolClient} from "pg";
import {
TestContainer,
StartedTestContainer,
PostgreSqlContainer, Wait, StartedPostgreSqlContainer
} from "testcontainers";
import {DatabaseConnection} from "../../main/repository/DatabaseConnection";
const fs = require('fs')
jest.useFakeTimers()
const initSqlScript = fs.readFileSync('./sql/init.sql').toString()
describe('User Repository tests', () => {
const port: number = process.env.DB_PORT ? +process.env.DB_PORT : 5432
let pool: Pool
let container: StartedPostgreSqlContainer
beforeAll(async () => {
container = await new PostgreSqlContainer("postgres:15")
.withDatabase(process.env.POSTGRES_DB || 'test')
.withUsername(process.env.POSTGRES_USER || 'test')
.withPassword(process.env.POSTGRES_PASSWORD || 'test')
.withExposedPorts(port)
.start();
pool = new Pool({connectionString: container.getConnectionUri()})
const client = await pool.connect()
await client.query(initSqlScript) // initializes my database
await client.release()
await DatabaseConnection.changeConnection(container.getConnectionUri()) // sets the connection for my DatabaseConnection to the test container
})
const userRepository = new UsersRepository()
const originalUser: User = {
dateOfBirth: "01-01-2000",
email: "test",
nickname: "test",
password: "test",
username: "test",
pending: true
}
afterEach(async () => {
await userRepository.clear()
})
it('should create a user in DB and return user with ID', async () => {
const createdUser = await userRepository.createUser(originalUser)
expect(createdUser.username).toBe(originalUser.username);
expect(createdUser.email).toBe(originalUser.email);
expect(createdUser.nickname).toBe(originalUser.nickname);
expect(createdUser.password).toBe(originalUser.password);
expect(createdUser.dateOfBirth).toBe(originalUser.dateOfBirth);
expect(createdUser.pending).toBe(originalUser.pending);
expect(typeof createdUser.userId).toBe("string")
});
})

However, when i run my test, it does not terminate. I have checked the database and the user is created. I have also tried just returning the user object i have as input instead of getting the user from the database, but that also does not work.

I am logging any connections to my pool and it only says 1 idle connection and no active connections. When debugging, all of my clients are released.

Also, it works when I just use my local database, but I don't want that.

答案1

得分: 0

我自己找到了解决方法!我配置了Jest来使用虚拟计时器,因为我在某处读到这样做可以帮助处理超时异常。我不知道这正是导致问题的原因!

英文:

Ok so I figured it out on my own! I configured Jest to use fake timers because I read somewhere that this would help with timeout exceptions. Little did I know that this was causing my problems!

huangapple
  • 本文由 发表于 2023年4月17日 02:26:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029606.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定