我正在尝试使用Jest对我一直在研究的Express API进行单元测试,但是数据库必须在运行测试之前准备就绪。但是,这似乎没有发生。我有一个server.ts文件,其中包含:

import App from './app';
import UsersController from './controllers/users.controller';

const app = new App();

app.initialize(
  [
    new UsersController(),
  ]
);

if (process.env.NODE_ENV !== 'test') {
  app.listen();
}

export default app;


app.initialize是aysnc函数,用于配置数据库并路由我的控制器。

在我的单元测试中,我有以下内容

import server from "../server";
import supertest from 'supertest';

const request = supertest(server.app);

it('should allow users to register', async () => {
    // Arrange
    const user = {
      firstName: 'John',
      lastName: 'Smith',
      age: 42
    };

    return request.post('/api/users')
      .send(user)
      .set('Accept', 'application/json')
      .then(response => {
        expect(response).toEqual(user.firstName)
        expect(response.body.lastName).toEqual(user.lastName)
        expect(response.body.id).toBeGreaterThan(0)
    });
});


但是,这会导致404错误,但是,如果我删除服务器文件中“测试”上的NODE_ENV检查,我可以看到在测试后好好调用了app.listen(),所以我相信可以肯定地认为测试是在该文件完成之前运行。

为了完整性,这是我的App类:

import "reflect-metadata";
import express from 'express';
import * as bodyParser from 'body-parser';
import {createConnection} from "typeorm";
import IController from './controllers/baseController.interface';

class App {
  public app = express();
  public port: number = 8080;
  public ready: boolean = false;

  public async initialize(controllers : [IController]) {
    await createConnection().then(async connection => {
      connection.synchronize();
      this.initializeMiddlewares();
      this.initializeControllers(controllers);
    });
  }

  private initializeMiddlewares() {
    this.app.use(bodyParser.json());
  }

  private initializeControllers(controllers : [IController]) {
    controllers.forEach((controller) => {
      this.app.use('/api/', controller.router);
    });
  }

  public listen() {
    this.app.listen(this.port, () => {
      console.log(`App listening on the port ${this.port}`);
    });
  }
}

export default App;

最佳答案

您可以尝试将App实例创建代码包装在一个函数中。然后,您可以在测试中等待它。在您的server.ts中执行以下操作:

import App from './app';
import UsersController from './controllers/users.controller';

const getApp = async () => {
   const app = new App();

  await app.initialize(
  [
   new UsersController(),
  ]
  );

}

getApp().then( appInstance => {
if (process.env.NODE_ENV !== 'test') {
   appInstance.listen();
}})

export default getApp;


在测试文件中,只需调用函数即可获取您的应用实例:

import getApp from "../server";
import supertest from 'supertest';


it('should allow users to register', async () => {
  const app = await getApp()
  const request = supertest(app);
  // Arrange
  const user = {
    firstName: 'John',
    lastName: 'Smith',
    age: 42
  };

 return request.post('/api/users')
   .send(user)
   .set('Accept', 'application/json')
   .then(response => {
     expect(response).toEqual(user.firstName)
     expect(response.body.lastName).toEqual(user.lastName)
     expect(response.body.id).toBeGreaterThan(0)
 });
});

09-25 17:41