The weird exception of calling done () in. end when using mocha plus supertest tests

  node.js, question

Test code

var utils = require('./utils');
 var request = require('supertest');
 var should = require('should');
 var app = require('../app');
 
 describe('addition', function () {
 //... previous test
 it('should return 2 given the url /add/1/1', function (done) {
 request(app)
 .get('/add/1/1')
 .expect(200)
 .end(function (err, res) {
 should.not.exist(err);
 parseFloat(res.text).should.equal(2);
 done();
 });
 });
 });

Route to be measured in app.js

app.get('/add/:first/:second', function (req, res) {
 Varsum = parsefloat (req.params.first) plus parseFloat(req.params.second);
 res.send(200, String(sum));
 });

Errors will be reported in the above tests.

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

But I did call done () in. end

Later I changed the code to (with done removed)

describe('addition', function () {
 //... previous test
 it('should return 2 given the url /add/1/1', function () {
 request(app)
 .get('/add/1/1')
 .expect(200)
 .end(function (err, res) {
 should.not.exist(err);
 parseFloat(res.text).should.equal(2);
 });
 });
 });

On the contrary, there was no mistake and the test passed. ………

✓ should return 2 given the url /add/1/1

I don’t understand the reason for this. ……

In theory, done is needed to remind mocha that asynchrony has been completed.

Description and Examples of mocha’s Official Website

Testing asynchronous code with Mocha could not be simpler! Simply invoke the callback when your test is complete. By adding a callback (usually named done) to it() Mocha will know that it should wait for completion.

describe('User', function() {
 describe('#save()', function() {
 it('should save without error', function(done) {
 var user = new User('Luna');
 user.save(function(err) {
 if (err) throw err;
 done();
 });
 });
 });
 });

Examples on supertest

describe('GET /users', function() {
 it('respond with json', function(done) {
 request(app)
 .get('/users')
 .set('Accept', 'application/json')
 .expect(200)
 .end(function(err, res) {
 if (err) return done(err);
 done();
 });
 });
 });

Everyone needs to call done, but as soon as I call done, I make a mistake. It is better not to call done.

Without done, the test cases are synchronized. At this time, the assertion of asynchronous callback to inside will not be executed, and the test case will pass. Presumably there is a problem with app inside’s code and the request has timed out.