【发布时间】:2020-12-31 00:18:13
【问题描述】:
2020 年 9 月 14 日更新
我有一个我编写的示例测试用例。当我运行这段代码时,测试用例通过了,但它抱怨说拆解没有正确发生并且有一个打开的连接。任何人都可以发现它是什么:
方法 1 - 内存泄漏
import { Connection, createConnection } from 'mongoose';
import __MONGO_URI__ from './__MONGO_URI__';
let conn: Connection | null = null;
const getConnection: (MONGO_DB_NAME: string) => Promise<Connection> = async MONGO_DB_NAME => {
if (conn == null) {
conn = await createConnection(__MONGO_URI__, {
dbName: MONGO_DB_NAME,
bufferCommands: false, // Disable mongoose buffering
bufferMaxEntries: 0, // and MongoDB driver buffering
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
}
return conn;
};
const MONGO_DB_NAME = 'mongo-test';
let db: Connection;
describe('mongo - connection test to ensure setup teardown', () => {
beforeAll(async done => {
db = await getConnection(MONGO_DB_NAME);
done();
});
afterAll(async done => {
if (conn) {
await db.dropDatabase();
await conn.close();
}
done();
});
it('true = true', () => {
expect(true).toBe(true);
});
});
错误:
工作进程未能正常退出并被强制退出。这可能是由于不正确的拆卸导致测试泄漏造成的。尝试使用 --runInBand --detectOpenHandles 运行以查找泄漏。
如果我把它全部剥离出来:
方法 2 - 内存泄漏
import { Connection, createConnection } from 'mongoose';
import __MONGO_URI__ from './__MONGO_URI__';
let conn: Connection | null = null;
const getConnection: (MONGO_DB_NAME: string) => Promise<Connection> = async MONGO_DB_NAME => {
if (conn == null) {
conn = await createConnection(__MONGO_URI__, {
dbName: MONGO_DB_NAME,
bufferCommands: false,
bufferMaxEntries: 0,
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
}
return conn;
};
const MONGO_DB_NAME = 'mongo-test';
let db: Connection;
describe('mongo - connection test to ensure setup teardown', () => {
beforeAll(async () => {
db = await getConnection(MONGO_DB_NAME);
console.log('db = ', db);
});
it('true = true', () => {
expect(true).toBe(true);
});
});
我还是有同样的问题
或者甚至这样做同样的问题:
方法 3 - 内存泄漏
import { Connection, createConnection } from 'mongoose';
import __MONGO_URI__ from './__MONGO_URI__';
let conn: Connection | null = null;
const getConnection: (MONGO_DB_NAME: string) => Promise<Connection | null> = MONGO_DB_NAME =>
new Promise(resolve => {
if (conn == null) {
conn = createConnection(__MONGO_URI__, {
dbName: MONGO_DB_NAME,
bufferCommands: false,
bufferMaxEntries: 0,
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
conn.on('connected', () => {
console.log('connected?');
resolve(conn);
});
}
resolve(conn);
});
const MONGO_DB_NAME = 'mongo-test';
let db: Connection;
describe('mongo - connection test to ensure setup teardown', () => {
beforeAll(async () => {
db = await getConnection(MONGO_DB_NAME);
console.log('db = ', db);
});
it('true = true', () => {
expect(true).toBe(true);
});
});
这种方法也有同样的问题
方法 4 - 内存泄漏
import mongoose from 'mongoose';
import __MONGO_URI__ from './__MONGO_URI__';
let conn: typeof mongoose;
const getConnection: (MONGO_DB_NAME: string) => Promise<typeof mongoose> = async MONGO_DB_NAME => {
if (!conn) {
conn = await mongoose.connect(__MONGO_URI__, {
dbName: MONGO_DB_NAME,
// bufferCommands: false,
// bufferMaxEntries: 0,
// useNewUrlParser: true,
// useUnifiedTopology: true,
// useCreateIndex: true
});
}
return conn;
};
const MONGO_DB_NAME = 'mongo-test';
let db: typeof mongoose;
describe('mongo - connection test to ensure setup teardown', () => {
beforeAll(async () => {
db = await getConnection(MONGO_DB_NAME);
console.log('db = ', db);
});
it('true = true', () => {
expect(true).toBe(true);
});
});
【问题讨论】:
-
那么,使用
--runInBand --detectOpenHandles运行的输出是什么? -
没有错误输出吗?
async和done是一种反模式。应该是async一个人。如果 dropDatabase 失败并且未达到关闭状态,则可能会出现问题。 -
--runInBand --detectOpenHandles 实际上并没有显示任何内容并且卡住并且没有退出测试
-
@EstusFlask 感谢您的反馈。导致内存泄漏的不是删除数据库或关闭连接。这是连接的实际创建。 createConnection 导致内存泄漏。如果我去掉代码只是为了shi。即使我删除了异步等待。
-
这不是连接本身导致泄漏,而是它被打开而不是关闭的事实。 Mongoose 连接肯定可以关闭,并且它们可以毫无问题地用于 Jest 测试。方法 2-4 在隔离问题方面没有任何价值,因为它们甚至不尝试关闭连接。按照我建议的方式尝试,去掉
done,因为它有缺陷并且可以抑制错误。调试await conn.close()真的被调用了。这是我在这里看到的唯一可能的问题。
标签: typescript mongoose async-await jestjs