Search code examples
node.jsasynchronoustimeoutmocha.jschai

Mocha times out calling async promise chain in Before hook despite using done


I'm running suite of async integration tests into a mongoose db using mocha and chai on node.js. Most are running fine but for one I have to carry out some pre-test db-prep with the before hook. When I use Done in the before hook Mocha times out.

Error I'm getting is "Error: Timeout of 5000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/Users/donfelipe/Sites/Agents/test/agents.js)"

Have tried moving the done() into a finally block at the end of the promise chain, but that just results in the the it block running before the async chain has finished executing. Kind of stumped.

/* 
    test case to check that the get function returns
*/
process.env.NODE_ENV = 'test-db';
'use strict'

const mongoose = require("mongoose");
const schemas = require('../app_api/models/schemas');
const agents = require('../app_api/controllers/agents.js');
const lists = require('../app_api/controllers/lists.js');
const server = require('../app.js');
const assert = require('assert')
const config = require('config')

//Require the dev-dependencies
const chai = require('chai');
const chaiHttp = require('chai-http');
const should = chai.should();

chai.use(chaiHttp);

describe('Agents test Suite', () => {
    beforeEach(() => {
        //don't have anything too do in this case
    })


    describe('/GET listAddItem suite', function () {

        //before we can test deletion we have to add at least one list in.
        const userModel = mongoose.model('User', schemas.userSchema);
        const agentModel = mongoose.model('Agent', schemas.agentSchema);
        let agentToAddId = {}
        const listObject = {
            listName: 'testList',
            _id: mongoose.Types.ObjectId(),
            agents: [{
                _id: "00000000000000000000000",
                name: "Test agent"
            }]
        }
        const lengthToTestAgainst = listObject.agents.length

        beforeEach((done) => {
             userModel.findById(config.defaultUserId)
                .select('agentList')
                .then((parentDoc) => {
                    if (!parentDoc) {
                        console.error('Unable to find user');
                    }
                    parentDoc.agentList.push(listObject)
                    return parentDoc.save()
                })
                .then(() => {
                    return agentModel.find({})
                })
                .then((response) => {
                    agentToAddId = response[0]._id
                    //console.log(response[0]._id);
                    done()
                })
        })

        it('should add a new item into the testList', (done) => {
            chai.request(server)
                .get(`/agents_api/listAddItem/${config.defaultUserId}/${listObject._id}/${agentToAddId}`)
                .end((err, response) => {
                    response.should.have.status(200)
                    response.body.agentList.testList.should.not.be.equal(lengthToTestAgainst + 1)
                    done(err)
                })

        })
    })

})

Solution

  • Duh. Resolved this myself. A real case of the tail wagging the dog. So I mocked up the call to the API that the chai.request(server) is making:

    /agents_api/listAddItem/${config.defaultUserId}/${listObject._id}/${agentToAddId}

    and submitted it through POSTMAN. Turns out there was a bug in the API and so it was not returning a response, so the timeout I was getting from Mocha was a valid response, the request was just hanging.