TypeScript + Mocha + Express - TypeError: app.address is not a function

TypeScript + Mocha + Express - TypeError: app.address is not a function

在将 API 从 ES6 转换为 TypeScript 时,我 运行 在尝试针对 Express REST 端点进行 运行 单元测试时遇到了这个问题:

TypeError: Cannot read property 'address' of undefined

我重新安排了一些加载服务器的代码,但基本上是这样的:

server.ts

import App from './app';

...bunch of imports...

new App([..., new Controller()]);

app.ts

export default class App {
    constructor(controllers) {
        this.app = express();

        this.initControllers(controllers);
    }

    initControllers(controllers) {
        controllers.forEach((controller) => {
            controller.setupRoutes(this.app);
        }
    }

}

然后每个控制器至少包含 setupRoutes() 函数,看起来像这样:

setupRoutes(app: Application): void {
    app.get(`/myRoute`, this.heartbeat);
}

当尝试调用 Spec 文件(仍然是 JS)中的路由时,我已经导入了 ../../build/app.js../../build/server.js 文件。如下所示进入超级测试产生了这些结果:

const server = require('../../build/server.js');
const app = require('../../build/app.js');

let supertest = require('supertest')(app);
产量: TypeError: app.address is not a function

let supertest = require('supertest')(app.default);
产量: Uncaught TypeError: Class constructor App cannot be invoked without 'new'

测试本身只是 ES6,而不是 TS。我还不打算将测试转换为 TS,并且此时仍希望为它们使用 ES6。

您必须将 http.Server 或 Express 应用程序传递给 supertest,您的 app (const app = require('../../build/app.js');) 只是一个包装 class。

你需要传递给supertest的是appInstance.app

我的建议:

在你的 App 中创建 express 实例到 public:

export default class App {
  constructor(controllers) {
    this.app = express();

    this.initControllers(controllers);
  }

  initControllers(controllers) {
    controllers.forEach((controller) => {
      controller.setupRoutes(this.app);
    });
  }

  // express instance getter
  getExpressInstance(): Application {
    return this.app;
  }

}

然后,在您的 server.ts 中,您必须导出 App 实例:

import App from './app';

...bunch of imports...

const app = new App([..., new Controller()]);

export default app;

最后,在您的 supertest 文件中:

const AppInstance = require('../../build/server.js');
// const app = require('../../build/app.js'); <----- remove unused import

let supertest = require('supertest')(AppInstance.getExpressInstance());