0

Trying to get a better understanding of it, I am testing this simple Express server (v 4 ) setup code :

server.js

import express from 'express';
import router from './routes';

const app = express();
app.use(router);

const server = app.listen(3000, function () {
  var port = this.address().port;
  /* eslint-disable no-console */
  console.log('Example app listening on port %s!', port);
});

export default app; // as suggested by Ron

with the following router

routes.js

var express = require('express');
var defaultController = require('./controllers/defaultController');

var router = express.Router();

router.get('/', defaultController.getHome);

module.exports = router;

it's clean ( eslinted) and running well with yarn start

I wrote ( copy/paste from tuts .. written in 2015) the following spec to test server.js with Jest and SuperTest

server.spec.js

var request = require('supertest');

describe('loading express', function () {
    var server; // http server object

    beforeEach(function () {
        delete require.cache[require.resolve('../src/server')];
        server = require('../src/server');
    });

    afterEach(function () {
        server.close();
    });

    it('responds to /', function testSlash(done) {
        request(server)
          .get('/')
          .expect(200, done);
    });

    it('404 everything else', function testPath(done) {
        request(server)
          .get('/foo/bar')
          .expect(404, done);
    });
});

But it's failing... with type error on .get().

TypeError: app.address is not a function

and type error on server.clos()

TypeError: server.close is not a function

Here is the full console.log

$ yarn test

    yarn run v1.9.4
    $ jest --runInBand --verbose
     FAIL  test/server.spec.js
      loading express
        ✕ responds to / (275ms)
        ✕ 404 everything else (1ms)

      ● loading express › responds to /

        TypeError: app.address is not a function

          16 |     it('responds to /', function testSlash(done) {
          17 |         request(server)
        > 18 |           .get('/')
             |            ^
          19 |           .expect(200, done);
          20 |     });
          21 |

          at Test.Object.<anonymous>.Test.serverAddress (node_modules/supertest/lib/test.js:55:18)
          at new Test (node_modules/supertest/lib/test.js:36:12)
          at Object.obj.(anonymous function) [as get] (node_modules/supertest/index.js:25:14)
          at Object.get (test/server.spec.js:18:12)

      ● loading express › responds to /

        TypeError: server.close is not a function

          11 |
          12 |     afterEach(function () {
        > 13 |         server.close();
             |                ^
          14 |     });
          15 |
          16 |     it('responds to /', function testSlash(done) {

          at Object.close (test/server.spec.js:13:16)

      ● loading express › 404 everything else

        TypeError: app.address is not a function

          22 |     it('404 everything else', function testPath(done) {
          23 |         request(server)
        > 24 |           .get('/foo/bar')
             |            ^
          25 |           .expect(404, done);
          26 |     });
          27 | });

          at Test.Object.<anonymous>.Test.serverAddress (node_modules/supertest/lib/test.js:55:18)
          at new Test (node_modules/supertest/lib/test.js:36:12)
          at Object.obj.(anonymous function) [as get] (node_modules/supertest/index.js:25:14)
          at Object.get (test/server.spec.js:24:12)

      ● loading express › 404 everything else

        TypeError: server.close is not a function

          11 |
          12 |     afterEach(function () {
        > 13 |         server.close();
             |                ^
          14 |     });
          15 |
          16 |     it('responds to /', function testSlash(done) {

          at Object.close (test/server.spec.js:13:16)

      console.log src/server.js:11
        Example app listening on port 3000!

    Test Suites: 1 failed, 1 total
    Tests:       2 failed, 2 total
    Snapshots:   0 total
    Time:        1.062s
    Ran all test suites.
    Jest did not exit one second after the test run has completed.

    This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • Split apart the app and the server; supertest just wants the Express app object, and you don't need to actually listen on a port for those tests. – jonrsharpe Dec 25 '18 at 08:58
  • I tried it. (. export default app; ) but got same errors ... in my server.js –  Dec 25 '18 at 09:27
  • FYI .. I tried to follow this tut : https://glebbahmutov.com/blog/how-to-correctly-unit-test-express-server/ –  Dec 25 '18 at 09:28
  • Note that the tutorial doesn't use `this` to access the server. But I'd still suggest keeping the app separate from the server, it avoids things like port conflicts (if you want to run the tests while the dev server is running). – jonrsharpe Dec 25 '18 at 10:22
  • Yes , you're right ... I updated my code .. however I got the same errors... –  Dec 25 '18 at 11:32
  • There is so much wrong with the tutorial I don't even know where to start(not your fault), for a start that's not a fricken unit test, that's an integration test - anywho - change your server.js to export default server? – Mrk Fldig Dec 25 '18 at 11:40

1 Answers1

0

For error:

TypeError: app.address is not a function

and

TypeError: server.close is not a function

Change

var server;
beforeEach(function() {
  delete require.cache[require.resolve('./server')];
  server = require('./server');
});

To:

var server;

beforeEach(function() {
  delete require.cache[require.resolve('./server')];
  server = require('./server').default;
});

Since you start HTTP server in server.js file which means when you execute require('./server') statement in your test file, the server will be started. You should close the server after all tests done. Otherwise, it will throw an error:

Error [ERR_SERVER_NOT_RUNNING]: Server is not running.

Change

afterEach(function(done) {
  server.close(done);
});

To:

afterAll(function(done) {
  server.close(done);
});

The app object created by express has no .close() method, but http.Server does.

Change:

const server = app.listen(3000, function() {
  var port = this.address().port;
  console.log('Example app listening on port %s!', port);
});

export default app;

To:

const server = app.listen(3000, function() {
  var port = this.address().port;
  console.log('Example app listening on port %s!', port);
});

export default server;

Integration test result with 100% coverage:

☁  jest-codelab [master] ⚡  npx jest --coverage --verbose /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/53920812/server.spec.js
 PASS  src/stackoverflow/53920812/server.spec.js
  loading express
    ✓ responds to / (741ms)
    ✓ 404 everything else (6ms)

  console.log src/stackoverflow/53920812/server.js:428
    Example app listening on port 3000!

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 routes.js |      100 |      100 |      100 |      100 |                   |
 server.js |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.865s, estimated 10s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/53920812

Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • Thank you for sharing. What's the purpose of closing the server after all tests? I want to close it after each test so my in-memory database is reset and my tests are independent. But if I do it on `afterEach()` I get `ERR_SERVER_NOT_RUNNING`. – chick3n0x07CC Jul 13 '20 at 15:22