I am looking for a correct way to completely reset my express server between tests! It seems that this is not just a problem for me, many other users have asked the same question, and many blog posts had been written on the argument. The proposed solutions are not working nor satisfactory for me. Here there is another similar question and an article that well describes the problem and suggests some solutions:
Stack overflow Closing an express server after running jasmine specs
Blog: https://glebbahmutov.com/blog/how-to-correctly-unit-test-express-server/
Here a package is specifically created to solve this problem: https://www.npmjs.com/package/server-destroy
Now, a minimal working example to reproduce my condition. In the code under test, an express server is created; when called on some endpoint, the server increments a value and returns it:
( function() {
'use strict'
const enableDestroy = require( 'server-destroy' )
const app = require( 'express' )()
const http = require( 'http' )
let val = 0
app.use( '/inc', (req, res) => {
val ++
res.send(val.toString())
} )
const server = http.createServer( app )
server.listen( 3000 )
enableDestroy(server);
module.exports = server
} )()
The test consists in two identical test cases; both of them call the server on the endpoint, and check the returned value.
before_each
and after_each
sections are provided in order to assure a new connection is created before the single test case is run, and then closed, to assure independence between the two test cases:
const chai = require( 'chai' )
const chaiHttp = require( 'chai-http' )
const expect = chai.expect
chai.use( chaiHttp )
let server
describe( 'first test group', () => {
beforeEach( () => {
server = require( './server' )
} ),
afterEach( ( done ) => {
server.destroy( done )
delete require.cache[require.resolve( './server' )]
} ),
it( 'should respond 1', ( done ) => {
chai.request( server )
.get( '/inc' )
.set( 'Connection', 'close' )
.end( ( err, res ) => {
expect( res.text ).to.be.equal( '1' )
done()
} )
} ),
it( 'should respond 1', ( done ) => {
chai.request( server )
.get( '/inc' )
.set( 'Connection', 'close' )
.end( ( err, res ) => {
expect( res.text ).to.be.equal( '1' )
done()
} )
} )
} )
The test fails because the server is not running after the first test. Please note that in the after_each
section I forced a cache cleaning for lost completely the last server instance. The test succeeds if a single test case is run:
first test group
✓ should respond 1
1) "after each" hook for "should respond 1"
1 passing (70ms)
1 failing
1) first test group
"after each" hook for "should respond 1":
Error: Not running
at Server.close (net.js:1620:12)
at emitCloseNT (net.js:1671:8)
at _combinedTickCallback (internal/process/next_tick.js:135:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
The configuration I used:
How can I solve this problem? And what does the error message mean?
It works with a little modification
I didn't use server-destroy
since server.close
works just fine
server.js
// ( function() { // no need for this
'use strict'
//const enableDestroy = require( 'server-destroy' )
const app = require( 'express' )()
const http = require( 'http' )
let val = 0
app.use( '/inc', (req, res) => {
val ++
res.send(val.toString())
} )
const server = http.createServer( app )
server.listen( 3000 )
// enableDestroy(server);
module.exports = server
// } )()
test.js
const chai = require( 'chai' )
const chaiHttp = require( 'chai-http' )
const expect = chai.expect
chai.use( chaiHttp )
let server
describe( 'first test group', () => {
beforeEach( () => {
server = require( './server' )
} ),
afterEach( ( done ) => {
// UPDATE DON'T CLOSE THE SERVER
delete require.cache[require.resolve( './server' )]
done()
//server.close( () => {
// delete require.cache[require.resolve( './server' )]
// done()
//})
} ),
it( 'should respond 1', ( done ) => {
chai.request( server )
.get( '/inc' )
.set( 'Connection', 'close' )
.end( ( err, res ) => {
expect( res.text ).to.be.equal( '1' )
done()
} )
} ),
it( 'should respond 1', ( done ) => {
chai.request( server )
.get( '/inc' )
.set( 'Connection', 'close' )
.end( ( err, res ) => {
expect( res.text ).to.be.equal( '1' )
done()
} )
} )
} )
this is after some time from the initial question.
On the chai-http documentation i could able to find that it has mechanism to open up the server connection using the keepOpen()
method from the request method. (actually it returns back an agent)
const chai = require("chai");
const chaiHttp = require("chai-http");
chai.use(chaiHttp);
const chaiAppServer = chai.request(server).keepOpen();
https://www.chaijs.com/plugins/chai-http/#integration-testing
But as it mentions, we have to manually close the server connection.
describe("TEST Case group", () => {
after(() => {
chaiAppServer.close();
});
//..... integration test cases
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With