Jest检测到以下1个打开的句柄可能会阻止Jest退出:TCPSERVERWRRAP



我在这里做一个基本的端到端测试,目前它正在失败,但首先我无法摆脱打开的句柄。

Ran all test suites.
Jest has detected the following 1 open handle potentially keeping Jest from exiting:
●  TCPSERVERWRAP
40 |     }
41 |     return request(app.getHttpServer())
> 42 |       .post('/graphql')
|        ^
43 |       .send(mutation)
44 |       .expect(HttpStatus.OK)
45 |       .expect((response) => {
at Test.Object.<anonymous>.Test.serverAddress (../node_modules/supertest/lib/test.js:61:33)
at new Test (../node_modules/supertest/lib/test.js:38:12)
at Object.obj.<computed> [as post] (../node_modules/supertest/index.js:27:14)
at Object.<anonymous> (app.e2e-spec.ts:42:8)
import { Test, TestingModule } from '@nestjs/testing'
import { HttpStatus, INestApplication } from "@nestjs/common";
import * as request from 'supertest'
import { AppModule } from '../src/app.module'
describe('AppController (e2e)', () => {
let app: INestApplication
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile()
app = moduleFixture.createNestApplication()
await app.init()
})
afterAll(async () => {
await app.close()
})
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(HttpStatus.OK)
.expect('Hello World!')
})
it('mutation', async () => {
const mutation = {
query: `mutation Create($title: String!) {
create(title: $title) {
id,
title
}
}`,
variables: {
title: 'Mon programme',
},
}
return request(app.getHttpServer())
.post('/graphql')
.send(mutation)
.expect(HttpStatus.OK)
.expect( (response) => {
expect(response.body).toBe({
id: expect.any(String),
title: 'Mon programme',
})
})
})
})

知道是什么挡住了测试选手的去路吗?

注意,由于我使用的是NestJs,所以在测试结束时不需要使用.end(done)方法。

附言:显然我在这个问题上有很多代码,我需要添加更多的细节,但不知道我能说什么。

我仍然没有找到一个完美的解决方案,但目前我选择了这个解决方案:

jest --config ./test/jest-e2e.json --forceExit

--forceExit选项以某种方式终止openHandles并解锁所有内容。然而,我仍然在寻找;适当的方式";处理这个问题。

这就是的问题

it('/ (GET)', () => {
return request(app.getHttpServer())
^^^^^^^^^^^^^^^^^^^^^
.get('/')
.expect(HttpStatus.OK)
.expect('Hello World!')
})

服务器未关闭,测试后仍处于打开状态。您需要创建一个变量来引用实例,并在每次测试后关闭它。我只是花了几个小时想弄清楚。希望这能帮助任何遇到类似问题的人。

下面是一个你的代码示例,我的修复想法是:

describe('AppController (e2e)', () => {
let app: INestApplication
let server: SERVER_TYPE
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile()
app = moduleFixture.createNestApplication()
await app.init()
// Reference the server instance
server = app.getHttpServer()
})
afterEach(async () => {
await app.close()
// Close the server instance after each test
server.close()
})
it('/ (GET)', async () => {
// Make the request on the server instance
return await request(server)
.get('/')
.expect(HttpStatus.OK)
.expect('Hello World!')
})

此外,我注意到您正在使用beforeEachafterAll。你每次都会为每个测试创建一个新的应用程序,所以我认为这也可能会给HTTP服务器带来一些问题。不过我不确定。

import { Test, TestingModule } from '@nestjs/testing'
import { HttpStatus, INestApplication } from "@nestjs/common";
import * as request from 'supertest'
import { AppModule } from '../src/app.module'
beforeEach(() => {
...
})
afterEach(() => {
...
})
describe('tests', () => {
...
})

但是,这只是我的偏好,取决于你

更新:本打算使用beforeEach而不是beforeAll,因为我们需要在EACH测试之前关闭服务器,而不是全局设置和拆卸。

更新2:否则使用async/await,它将始终通过,因为请求是异步的,除非您等待它完成,否则不会完成。

您正在重新创建整个应用程序beforeEach,但仅在afterAll中将其拆除,这意味着您可能在这一过程中泄漏了一些内存。您正在为应用程序变量分配一个新实例,但很可能有隐藏的引用阻止垃圾收集器清除前一个实例,比如request函数获得的引用。

beforeEach改成beforeAll,你就可以走了。

对于任何仍然遇到错误的人,即使您已经关闭了连接及其间歇性错误,您可以尝试添加--no-cache --watchAll。以下是完整的语法:

"test": "jest --watchAll --no-cache --detectOpenHandles"

也有同样的问题。

"test:e2e": "jest --config ./test/jest-e2e.json --no-cache --detectOpenHandles",

对我来说效果很好

不要使用it,而是尝试使用test并将done作为参数传递并调用它。这对我有效。

test('mutation', async (done) => {
const mutation = {
query: `mutation Create($title: String!) {
create(title: $title) {
id,
title
}
}`,
variables: {
title: 'Mon programme',
},
}
const response = request(app.getHttpServer())
.post('/graphql')
.send(mutation)
expect(response).to.be(HttpStatus.Ok)
done()
})

//在每个测试上

it('the description', (done) => {
request(app)
.get('/some-path')
.end(done);
});

Toomuchrice4u的回答帮助了我。我在组件使用的一个服务中有一个注销方法,所以我在afterEach中调用了它,如下所示:

afterEach(async () => {

await userService.logout();

});

还要检查scripts部分中的package.json文件以查找test:e2e密钥。检查其值并删除参数--detectOpenHandles。脚本的键值对可以如下:"test:e2e": "jest --config ./test/jest-e2e.json --forceExit"

最新更新