我在这里做一个基本的端到端测试,目前它正在失败,但首先我无法摆脱打开的句柄。
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!')
})
此外,我注意到您正在使用beforeEach
和afterAll
。你每次都会为每个测试创建一个新的应用程序,所以我认为这也可能会给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"