Mocha and nodejs troubles

When I am attempting to start up my node server from my test script and making a request to it, it always responds back with status code 404.

var assert = require('assert');
var express = require('express');
var request = require('request');
var status = require('http-status');
var expect = require('chai').expect;

describe('Server initialization', function() {
  var url = 'http://localhost:3000';
  var app = express();
  var server;

//creating a separate instances of the server
  before(function() {
    server = app.listen(3000);
  });
  
  after(function() {
    server.close();
  });

//This is where the test fails
  it('sending request to server', function(done) {
    request(url, function(error, res) {
      //The status code always returns as 404, although the url is correct.
      expect(res.statusCode).to.deep.equal(200)
      done();
    })
  });

  it('index page should have "Hello World"', function(done) {
    request(url, function(error, res) {
      expect(res.body).to.equal('Hello World');
      done();
    });
  });
});

If I comment out my before() and after() hooks and start up the server manually, then the test conditions work fine. But I foresee that getting in the way of development. Is there something I am missing here? Has anyone ever encountered this before?

I don’t have any experience with testing, but I guess it gives an error because app.listen() is async.

This should work (I guess):

before(function(done){
  server = app.listen(3000, done);
});

https://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback

I gave that a try and I’m still getting a false negative :frowning:

Apparently you don’t need the done in before.

This is the changed file:

var assert = require('assert');
var request = require('request');
var status = require('http-status');
var expect = require('chai').expect;

var app = require("./server");

describe('Server initialization', function() {
  var url = 'http://localhost:3000';

//creating a separate instances of the server
  before(function() {
    server = app.listen(3000);
  });
  
  after(function() {
    server.close();
  });

//This is where the test fails
  it('sending request to server', function(done) {
    request(url, function(error, res) {
      //The status code always returns as 404, although the url is correct.
      expect(res.statusCode).to.deep.equal(200);
      done();
    })
  });

  it('index page should have "Hello World"', function(done) {
    request(url, function(error, res) {
      expect(res.body).to.equal('Hello World');
      done();
    });
  });
});

And this is server.js:

var express = require("express");

app = express();
server = app.listen();

app.get("/", (req,res) => {
  res.send("Hello World");
});

module.exports = app;

Should work this way.

1 Like

Hello DanStockham,

I have modified your code to show an example of a basic test, done with chai && mocha && supertest.

You don’t need “before” and “after” functions to manage your app, just let supertest take care of your requests.

Here is the /server.js

  let express = require("express");
  let app = express();

  app.get('/', function(req, res) {
    res.send({
      message: 'Hello World'
    });
  });

  module.exports = app;

And the /tests/test.js

  process.env.NODE_ENV = 'test';

  let request = require('supertest');
  let expect = require('chai').expect;

  let server = require('../server');

  describe('Server initialization', function() {
    it('sending request to server', function(done) {
      request(server).get('/').end(function(err, res) {
        expect(res.statusCode).to.equal(200);
        done();
      });
    });

    it('Should have a property "message" that equals "Hello World"', function(done) {
      request(server).get('/').end(function(err, res) {
        expect(res.body)
          .to.be.an('object')
          .with.property('message')
          .that.is.a('string')
          .that.equal('Hello World');
        done();
      });
    });
  });

Hope this helps,

Don’t you have to manually start the server before you run the test?

Nope, you just import your server app and pass the object to your requests this way:

let server = require('../server');

request(server).get('/').........

Supertest is an http client modified specially for testing, so the module will do the server start/stop for you.

Regards