Say I have some controller logic:
// registered for route POST /login
function login(req, res, next) {
User.findOne({username: req.body.username}).exec()
.then(user => {
if (user) {
return bcrypt.compareAsync(req.body.password, user.password)
} else {
throw new APIError("Unauthorized", 401)
}
})
.then(some more chained promises)
.catch(next)
}
- The route works fine in development server.
- I have implemented error handling middleware. The 401 error can be correctly propagated to the middleware and gives a 401 response.
- I use Mocha + Supertest (and Sinon + SinonTest when I need to stub some methods) to test.
- The test of the happy path can pass.
- Tests for sad paths produced by other middlewares before the controller (such as express-validation) are detected correctly in the test.
But when it comes to testing sad paths in the controller, it always gives timeout error:
it('throws unauthorized error if no user match', () => {
return request(app)
.post('/login')
.send({ username: 'notExistInDB', password: 'asdfasd'})
.expect(401)
})
This test fails with error message:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Things I have tried so far but did not work:
- use Mocha's
done()
callback instead of returning the Supertest promise - stub all async calls to return immediately
- increase the timeout
Please help if you have any clue about what is possibly going wrong. This really bugs me because I cannot test any sad paths in the controller and when a test fails I can never see the actual error.