如何修复 mocha/chai 在 NestJS API 上抛出 "app.address()" 错误的测试?

How to fix test with mocha/chai throwing "app.address()" error on NestJS API?

我正在尝试使用 Mocha 和 Chai 测试我的 API 路线,但我得到的只是 "TypeError".

这是我的 main.ts 文件:

import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';

export async function bootstrap(): Promise<any> {
  const app = await NestFactory.create(AppModule);
  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('api', app, document);

  return await app.listen(3000);
}
const appServer = bootstrap();
export default appServer;

最初 "bootstrap" 函数没有 returning 任何东西,但我最终将其 return 导出 app.listen。

这是我的测试文件:

import * as chai from 'chai';
import chaiHttp = require('chai-http');
import 'mocha';
import appServer from '../src/main';

chai.use(chaiHttp);

describe('first test', () => {
  it('should return hello world', async () => {
    const res = await chai.request(appServer).get('/notes');
    chai.expect(res.text).to.equal('hello');
  });
});

这是我在启动时得到的 "npm test"。错误发生在 "node_modules/chai-http/lib/request.js" 文件中。

TypeError : app.address() is not a function

我尝试 console.log(app) 在 "request.js" 文件中,这就是我得到的

promise { < pending > }

而且我也尝试在 main.ts

中纠正这个问题
console.log(app.address())

但是 Visual Code 立即警告我这个错误

Property 'address' does not exist on type 'INestApplication'.ts(2339)

NestFactory 与 Chai 兼容吗?感觉我在"main.ts"中导出的"app"不符合shai的要求。我很困惑。

这是经过编辑的可接受的解决方案,以使其正常工作

import * as chai from 'chai';
import chaiHttp = require('chai-http');
import 'mocha';
import { AppModule } from '../src/app.module';
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';

chai.use(chaiHttp);

describe('first test', () => {
  let app: INestApplication;

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

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

  it('should return hello world', async () => {
    const res = await chai.request(app.getHttpServer()).get('/notes');
    chai.expect(res.text).to.equal('hello');
  });

});

从外观上看,chai-http 需要一个 Express/Connect 应用程序或原始 Node HTTP 服务器。 chai.request 你可能需要的是使用 app.getHttpServer() 以便你获得底层服务器,因为 Nest 实际上是围绕 Express/Fastify.

的自以为是的语法包装器

编辑

由于在测试上下文中不需要 SwaggerModule,我建议遵循与此类似的内容:

import * as chai from 'chai';
import chaiHttp = require('chai-http');
import 'mocha';
import { AppModule } from '../src/app.module';

describe('first test', () => {
  let app: INestApplication;

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

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

  it('should return hello world', async () => {
    const res = await chai.request(app.getHttpServer()).get('/notes');
    chai.expect(res.text).to.equal('hello');
  });

});

从这里开始,如果您需要覆盖任何服务、守卫、管道、拦截器或过滤器,您可以在链接到 compile() 调用之前使用相应的 override*() 方法。这与使用 supertest 进行测试的方法非常相似。