6

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)
}
  1. The route works fine in development server.
  2. I have implemented error handling middleware. The 401 error can be correctly propagated to the middleware and gives a 401 response.
  3. I use Mocha + Supertest (and Sinon + SinonTest when I need to stub some methods) to test.
  4. The test of the happy path can pass.
  5. 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:

  1. use Mocha's done() callback instead of returning the Supertest promise
  2. stub all async calls to return immediately
  3. 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.

Jack Ye
  • 61
  • 2

0 Answers0