Crystal Rae Bryant Crystal Rae Bryant - 17 days ago 7
Node.js Question

Mocha tests not failing when they should

I'm trying to test my routes file, and mocha is returning success for all of my expects, even though I've coded a couple that should absolutely fail. I added a 2+2 = 5 test just to make sure something would fail. I have done() in my assertion blocks.

I'm using a MEAN stack, and I tried to test the node files with jasmine, since I'm already using that to test the Angular files, but got tons of crazy errors, so I threw all that out and decided to give mocha a try instead.

Results:

Routes
1) makes sure something fails
GET /
√ returns status code 200
GET /nonexistent
√ returns status code 400
GET /api/todos
√ returns status code 200
√ returns a list of todos


Test file

// test/routes.spec.js

var request = require('request');
var expect = require('chai').expect;

describe('Routes', function() {

var base_url = "http://localhost:8080/"

// does fail as expected
it("makes sure something fails", function () {
expect(2 + 2).to.equal(5);
});

describe("GET /", function() {
it("returns status code 200", function() {
request(base_url, function(error, response, body) {
expect(response.statusCode).to.equal(200);
done();
});
});
});

//should fail
describe("GET /nonexistent", function() {
it("returns status code 400", function () {
request(base_url + "/nonexistent", function (error, response, body) {
expect(response.statusCode).to.equal(200);
done();
});
});
});

describe("GET /api/todos", function() {
it("returns status code 200", function() {
request(base_url + "/api/todos", function(error, response, body) {
expect(response.statusCode).to.equal(200);
done();
});
});

//should fail
it("returns a list of todos", function() {
request(base_url + "/api/todos", function(error, response, body) {
console.log(body);
expect(body).to.equal("abcd");
done();
});
});
});

});


Routes file:

// app/routes.js

var Todo = require('./models/todo');

module.exports = function(app) {

// api ---------------------------------------------
// get all todos
app.get('/api/todos', function (req, res) {
Todo.find(function (err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});

// create todo and send back all todos after creation
app.post('/api/todos', function (req, res) {
Todo.create({
text: req.body.text,
done: false
}, function (err, todo) {
if (err)
res.send(err);

Todo.find(function (err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});

// delete a todo
app.delete('/api/todos/:todo_id', function (req, res) {
Todo.remove({
_id: req.params.todo_id
}, function (err, todo) {
if (err)
res.send(err);

Todo.find(function (err, todos) {
if (err)
res.send(err)
res.json(todos);
})
})
})

// application --------------------------------------
app.get('*', function (req, res) {
res.sendFile(__dirname + '/public/index.html');
});
};

Answer

You want to use the done callback but none of your tests declare it in the parameters of the callbacks passed to it. Your first test, for instance, should be:

it("returns status code 200", function (done) { // <== Add parameter here!
    request(base_url, function(error, response, body) {
        expect(response.statusCode).to.equal(200);
        done();
    });
});

Without the parameter, Mocha considers the test to be synchronous. So it does not wait for request to call its callback, and ends right away. The fact that done is undefined does not lead to an error because the JavaScript interpreter does not get to done() before Mocha deems the tests over.

Comments