首页 > 解决方案 > TypeScript + Mocha + Express - TypeError: app.address 不是函数

问题描述

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

TypeError: Cannot read property 'address' of undefined

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

服务器.ts

import App from './app';

...bunch of imports...

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

应用程序.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。

标签: javascriptnode.jstypescriptexpressmocha.js

解决方案


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

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

我的建议:

将您的应用程序中的快速实例公开:

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());

推荐阅读