Here's a trivial trivial koa
server implementation:
const Koa = require('koa')
const api = require('./resources')
const createServer = () => {
const app = new Koa()
app.use(api.routes())
app.use(api.allowedMethods())
return app
}
module.exports = createServer
And a simple test:
const request = require('supertest')
const createServer = require('../src/server')
const { knex } = require('../src/config/db')
let server
beforeAll(() => {
server = createServer().listen(8081)
return server
})
beforeEach(() => {
return () => {
knex.migrate.latest()
knex.seed.run()
}
})
afterEach(() => {
return () => {
knex.migrate.rollback()
}
})
afterAll(() => {
server.close()
})
describe('routes: /api/users', () => {
describe('GET /users', () => {
test('should return json', async () => {
const response = await request(server).get('/api/users')
expect(response.status).toEqual(200)
expect(response.type).toEqual('application/json')
expect(response.body).toHaveLength(3)
})
})
})
I will skip the example route for brevity sake as the test passes successfully. But then it hangs, and running jest --detectOpenHandles
produces:
Jest has detected the following 1 open handle potentially keeping Jest from exiting:
● TCPSERVERWRAP
6 |
7 | beforeAll(() => {
> 8 | server = createServer().listen(8081)
| ^
9 | return server
10 | })
11 |
at Application.listen (node_modules/koa/lib/application.js:82:19)
at Object.<anonymous> (__tests__/routes.test.js:8:27)
Why does this occur and how can I fix it?
There are several problems.
return server
doesn't affect anything, it can be removed. But beforeAll
doesn't wait for the server to start, it should be:
beforeAll(done => {
server = createServer().listen(8081, done)
})
beforeEach
and afterEach
return functions that are not executed, promises from Knex aren't chained, it should be:
beforeEach(async () => {
await knex.migrate.latest()
await knex.seed.run()
})
afterEach(async () => {
await knex.migrate.rollback()
})
afterAll
doesn't wait for server connection to be closed, which is likely the cause for this error, it should be:
afterAll(done => {
server.close(done)
});