使用Testcontainers的Jest数据库测试无法终止问题求助
Node.js(TypeScript) + Postgres 15 + Testcontainers 测试无法终止问题
我正在为Node.js(TypeScript)应用的数据库编写测试,使用Postgres 15和Testcontainers。手动运行代码正常,数据库客户端已正确释放,但测试始终无法终止。
要测试的createUser方法会调用getUserById,后者又会调用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() } }
DatabaseConnection中维护了一个Client Pool,getClient方法从池中获取客户端。
测试代码如下:
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") }); })
运行测试时,数据库中已成功创建用户,但测试无法终止。我尝试直接返回输入的用户对象而非查询数据库,问题依然存在。
日志显示连接池仅1个空闲连接,无活跃连接,调试确认所有客户端均已释放。使用本地数据库时测试可正常终止,但我希望使用Testcontainers。
内容的提问来源于stack exchange,提问作者Julia Mayrhauser
相关产品推荐
相关产品推荐

