簡體   English   中英

Nest e2e 測試:測試運行完成后一秒 Jest 沒有退出

[英]Nest e2e test : Jest did not exit one second after the test run has completed

我在 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.

這是我的 controller 的代碼

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
}

有時您可能會遇到來自 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運行的建議並不總能就問題所在提供可操作的反饋。

一個名為泄漏句柄的替代社區 package 可用,它可能有助於追查罪魁禍首。 將此 package 安裝到具有非退出測試的項目的dev dependencies項中,並將代碼require('leaked-handles)放在測試文件的頂部。 觀察任何 output 關於測試運行器中的泄漏。 它通常會准確地告訴您哪些端口或服務仍處於活動狀態並阻止測試關閉。

如果您捕獲此 output 並在此處分享,我們將能夠幫助您更詳細地了解可能缺少哪些清理邏輯。

邊注:

我通常建議您在beforeAllafterAll生命周期方法中進行模塊級啟動和拆除,而不是在每個測試之間進行。 它可能與您的問題無關,但會對您的測試套件運行多長時間產生很大影響

可能為時已晚,但您必須從模塊變量中調用 close function,如下所示:

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

那對我有用。

Redis 也有這個問題。 --detectOpenHandles標志與 Jest 一起使用時看到TCPSERVERWRAP

作為一種解決方法,您可以將--forceExit標志傳遞給 Jest。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM