Search code examples
javascriptnode.jsexpressunit-testingsupertest

Express javascript unit test 'TypeError: app.address is not a function'


I have checked other answers like this one Mocha API Testing: getting 'TypeError: app.address is not a function' and it seems the main issue for the error is not exporting the server but I think I am doing that.

Here is my test file spec.js

var request = require('supertest');
describe('loading express', function () {
  var server;
  beforeEach(function () {
  delete require.cache[require.resolve('./index')];
  server = require('./index');
});
  afterEach(function (done) {
    server.close(done);
  });
  it('responds to /', function testSlash(done) {
  request(server)
    .get('/')
    .expect(200, done);
  });

Here is my index.js file

import bodyParser from "body-parser";
import cookieParser from "cookie-parser";
import cors from "cors";
import express from "express";
import _ from "lodash";
import serveStatic from "serve-static";

const port = 8000;

export default (app) => {
  app.use(express.json({ limit: "50mb" }));
  app.use(
    express.urlencoded({
      extended: true
    })
  );
  app.use(bodyParser.json({ limit: "50mb" }));
  app.use(cors());
  app.use(serveStatic("dist/", { index: ["index.html"] }));
  app.use(cookieParser());

  if (_.isNil(process.env.APP_ENV)) {
    process.env.APP_ENV = "LOCAL";
  } 
  // ... A load of variables and functions in here

  // simple function to test
  app.get('/', function (req, res) {
     res.status(200).send('ok');
   });

   var server = app.listen(port, function () {
   var port = server.address().port;
   console.log('Example app listening at port %s', port);
 });
  module.exports = server;
};

Solution

  • index.js is exporting a function which takes app as an argument. So the import of index.js is a function which must be called with app.

    spec.js

      server = require('./index');
      // replace with
      server = require('./index')(app);
    

    Assuming this remains as a function, and you call it with app in spec.js, as above, then you can get server by replacing module.exports = server; with return server;.

    test.js

      module.exports = server;
      // replace with
      return server;
    

    Separately, there is also a mixture of ES Modules (import/export) and CommonJS Modules (module.exports/require) here which can result in a variety of weird behavior. If you can standardize on just one of these, it'll go a long way.

    But if you continue to use require('./index') to import index.js which is an ES Module, you may need to try require('./index').default instead, to grab that default export.