I've been trying for the last 2 days to figure out why the test is not existing despite following all the steps with no luck until by accident I left the 'done' parameter in afterAll() without actually explicitly calling it from inside. like this: afterAll((done)=>{ mongoose.disconnect() }). This made it exit and work properly but when I explicitly call donefrom the function using promises (async/await or then) or as a callback to mongoose.disconnect() such as afterAll(async (done)=> { await mongoose.disconnect(); done()})it does not exit and keeps hanging. when using --detectOpenHandles it tells me that app.listen(3001) is the potential open handler which I explicitly closed. I can't figure if this is a problem in my code or a bug. The way I was able to fix the problem above by passing done param without using it seemed more of a hack (or bug) than a real solution. is done supposed to do anything if it is passed only(without being called)?
``
const request = require('supertest');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/debugging');
const app = require('../app');
let server = '';
describe('GET /products/:name', ()=>{
beforeEach(()=> { server = app.listen(3001)})
afterEach(()=> { server.close() })
// afterEach((done)=> { server.close(done) }) <-- this does not work also
afterAll((done) => {
mongoose.disconnect();
// done(); <--- does not work even when using await on mongoose
// mongoose.disconnect(done); <--- does not work also
})
it('should return a 404 status', async ()=>{
const res = await request(server).get('/name');
expect(res.status).toBe(404);
})
})
when I explicitly call done() in afterAll I get this:
Jest has detected the following 1 open handle potentially keeping Jest from exiting:
● TCPSERVERWRAP
8 |
9 |
> 10 | beforeEach(()=> { server = app.listen(3001)})
| ^
11 | afterEach(()=> { server.close() })
12 | // afterEach((done)=> { server.close(done) }) <-- this does not work also
13 | afterAll((done) => {
at Function.listen (node_modules/express/lib/application.js:618:24)
at Object.listen (tests/routes.test.js:10:36)
```
To be able to exit process when calling done after disconnecting from server and db.
to reproduce behaivor here is a sample rep here. note that the sample I provide is a working. Just try to call done using any method and the test will hang. also try removing the done param from afterAll() and the test will also hang.
Hey @tito300 this is happening because mongoose.disconnect() is a promise and you need to wait until the disconnect promise is resolved. It looks like you tried this a few ways but none of them were correct.
What did work (providing the done arguments without calling) only works because it's basically forcing Jest to wait for a done that is never called, so the open handle detection never runs
Here's why a few of your attempts were wrong:
This will call done before the promise resolves (i.e. before it's done)
afterAll((done) => {
mongoose.disconnect(); // 1 - start the disconnect
done(); // 2 - call done
// 3 - sometime later the disconnect actually happens
})
This will pass done to disconnect, which would work if disconnect accepted a callback (it does not)
afterAll((done) => {
mongoose.disconnect(done);
})
Two ways that should work are:
// pass done to .then
afterAll(done => {
mongoose.disconnect().then(done);
})
// return the promise
afterAll(() => {
return mongoose.disconnect();
})
Give these a try and let me know if they work!
Same issue here. The async handlings proposed by @rickhanlonii did not work :(
Most helpful comment
Hey @tito300 this is happening because
mongoose.disconnect()is a promise and you need to wait until the disconnect promise is resolved. It looks like you tried this a few ways but none of them were correct.What did work (providing the done arguments without calling) only works because it's basically forcing Jest to wait for a
donethat is never called, so the open handle detection never runsHere's why a few of your attempts were wrong:
This will call
donebefore the promise resolves (i.e. before it's done)This will pass done to disconnect, which would work if disconnect accepted a callback (it does not)
Two ways that should work are:
Give these a try and let me know if they work!