【问题标题】:Nest e2e test : Jest did not exit one second after the test run has completedNest e2e 测试:测试运行完成后一秒钟 Jest 没有退出
【发布时间】:2021-03-28 20:30:18
【问题描述】:

我在 nestJs 微服务中进行了一些 e2E 测试(使用 Redis 作为传输器)。 一切都很顺利,只是这个过程永远不会结束。

这是控制台上显示的消息

Ran all test suites.
Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

这是我的控制器的代码

import {Body, Controller, HttpCode, Post, Query} from '@nestjs/common';
import { AppService } from './app.service';
import {Client, ClientProxy, MessagePattern, Transport} from '@nestjs/microservices';
import {AdminDto} from "./admin.dto";
import {Admin} from "./admin.interface";
import {Observable} from "rxjs";

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  /** Useful for test only **/
  @Client({ transport: Transport.REDIS })
  client: ClientProxy;

  @Post()
  @HttpCode(200)
  call(@Query('command') cmd, @Body() data: any): Observable<any> {
    return this.client.send<number>({ cmd }, data);
  }
  /** End of test **/

  @MessagePattern({cmd: 'createAdmin'})
  async createClient(adminDto: AdminDto): Promise<Admin> {
    return await this.appService.create(adminDto);
  }
}

这是我的 app.e2e-soec.ts 文件,如您所见,我关闭了 afterEach 功能上的所有连接。

import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import {Transport} from "@nestjs/microservices";
import {AppModule} from "../src/app.module";
import * as mongoose from "mongoose";
import {connection} from "mongoose";

describe('AppController (e2e)', () => {
  let server;
  let app: INestApplication;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = module.createNestApplication();
    server = app.getHttpAdapter().getInstance();

    app.connectMicroservice({
      transport: Transport.REDIS,
      options: {
        url: 'redis://0.0.0.0:6379',
      },
    });
    await app.startAllMicroservicesAsync();
    await app.init();
  });
    
  it(`/POST (create admin)`, done => {
    const adminDto = {
      firstName : 'test',
      lastName: 'toto',
      password: '1234',
      email: 'test@toto.fr',
      roles: ['ROLE_ADMIN']
    };

    return request(server)
        .post('/?command=createAdmin')
        .send(adminDto)
        .end((error, response) => {
          expect(response.status).toEqual(200);
          expect(response.body).toMatchObject({
            _id: expect.any(String),
            firstName: "test",
            lastName: "toto"
          });
          done();
        });
  });

  afterEach(async done => {
    await mongoose.connection.close();
    await connection.close();
    await app.close();
    done();
  });
});

编辑

根据 Jesse Carter 的建议,我已添加 leaked-handles 以获得更多线索

好像是因为redis

tcp handle leaked at one of: 
    at RedisClient.Object.<anonymous>.RedisClient.create_stream (/Users/myUser/project/admin-service/node_modules/redis/index.js:195:31)
tcp stream {
  fd: 38,
  readable: true,
  writable: true,
  address: { address: '127.0.0.1', family: 'IPv4', port: 54468 },
  serverAddr: null
}

【问题讨论】:

    标签: jestjs nestjs


    【解决方案1】:

    可能晚了,但你必须从模块变量中调用 close 函数,如下所示:

    afterEach(async done => {
      for (const connection of connections) {
        await connection.close();
      }
      await app.close();
      await module.close(); // <-- this line
      done();
    });
    

    这对我有用。

    【讨论】:

      【解决方案2】:

      有时您可能会遇到来自 Jest 的错误,表明它没有正确退出,例如:

      Jest did not exit one second after the test run has completed. This usually means that there are asynchronous operations that weren't stopped in your tests.
      Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
      

      这通常表明确实存在问题,不应忽视。但是,接受使用 --detectOpenHandles 运行的建议并不总能就问题所在提供可操作的反馈。

      一个名为leaked-handles 的替代社区包可用,它可能有助于追查罪魁祸首。将此包安装到您的 dev dependencies 以用于具有非退出测试的项目,并将代码 require('leaked-handles) 放在测试文件的顶部。观察有关测试运行器泄漏的任何输出。它通常会准确地告诉您哪些端口或服务仍处于活动状态并阻止测试关闭。

      如果您捕获此输出并在此处分享,我们将能够帮助您更详细地了解可能缺少哪些清理逻辑。

      旁注:

      我通常建议您在 beforeAll 和 afterAll 生命周期方法中进行模块级启动和拆除,而不是在每个测试之间进行。它可能与您的问题无关,但会对您的测试套件运行多长时间产生很大影响

      【讨论】:

      • 感谢您的回答,我编辑了更多详细信息
      • 我也面临同样的问题。发现Redis连接不关闭后,如何解决?
      【解决方案3】:

      Redis 也有这个问题。在 Jest 中使用 --detectOpenHandles 标志时看到 TCPSERVERWRAP。

      作为一种解决方法,您可以将 --forceExit 标志传递给 Jest。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-05
        • 2018-12-08
        • 1970-01-01
        • 2019-06-15
        • 2019-09-16
        • 2019-05-24
        • 2023-03-13
        • 2021-03-01
        相关资源
        最近更新 更多