Reputation: 4287
While testing with Mocha I am getting the following error on running server.test.js
1) "before each" hook for "should get all todos":
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
server.test.js
const expect = require('expect');
const request = require('supertest');
const {app} = require('./../server');
const {Todo} = require('./../todos');
const todos = [
{
text: 'This is text 1'
},
{
text: 'This is text 2'
}
];
beforeEach((done) => {
Todo.remove({}).then(() => {
return Todo.insertMany(todos);
}).then(() => done());
});
describe('GET /todos', () => {
it('should get all todos', (done) => {
request(app)
.get('/todos')
.expect(200)
.expect(res => {
expect(res.body.length).toBe(2);
})
.end(done);
});
});
But if I do some changes in beforeEach() method like:
updated server.test.js
const expect = require('expect');
const request = require('supertest');
const {app} = require('./../server');
const {Todo} = require('./../todos');
const todos = [
{
text: 'This is text 1'
},
{
text: 'This is text 2'
}
];
beforeEach((done) => {
Todo.remove({}).then(() => {
Todo.insertMany(todos);
done();
})
});
describe('GET /todos', () => {
it('should get all todos', (done) => {
request(app)
.get('/todos')
.expect(200)
.expect(
expect(res.body.length).toBe(2);
})
.end(done);
});
});
Then I am getting no errors. Basically, by chaining promises in beforeEach() method I am running into an error but without that everything is fine. Could anyone explain why is it happening?
server.js
var express = require('express');
var body_parser = require('body-parser');
const {mongoose} = require('./mongoose.js');
const {Todo} = require('./todos');
const {Todo_1} = require('./todos');
var app = express();
app.use(body_parser.json());
// using GET method
app.get('/todos', (req, res) => {
Todo.find().then((todos) => {
res.send(todos);
}, (err) => {
res.status(400).send(err);
});
});
module.exports = {app}
app.listen(3000, () => {
console.log('Server is up on the port 3000');
})
Upvotes: 3
Views: 893
Reputation: 187
instead of putting localhost in the url like this: "mongodb://localhost:27017/yourDbName"
use 127.0.0.1, so it becomes like the following:
"mongodb://127.0.0.1:27017/yourDbName"
I do not know what is the reason behind this solution, but it seems that the server needs some time to process and figure out what the IP of the localhost is.
Hopefully this solution solves your issue.
Upvotes: 0
Reputation: 222319
This is incorrect way to handle promises:
Todo.remove({}).then(() => {
Todo.insertMany(todos);
done();
})
});
Todo.insertMany
is likely asynchronous and returns a promise, and it's detached from promise chain. If there are errors, they will result in unhandled promise rejections, and since tests depend on inserted rows, this will result in race condition:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
means exactly what it says. done
either wasn't called, or there was a timeout. It is possible for done
to never be called because errors aren't handled. It should be .then(done, done)
.
Since Mocha supports promises, a proper way is:
beforeEach(() =>
Todo.remove({})
.then(() => Todo.insertMany(todos))
);
Every promise that appears somewhere in promise chain should be returned.
Upvotes: 1