Mocha and nodejs troubles

Mocha and nodejs troubles
0.0 0

#1

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?


#2

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


#3

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


#4

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.


#5

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,


#6

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


#7

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