I'm trying to make sure my app gets properly destroyed after all my Jest tests have run, but I'm running into some very strange behaviour trying to use Jest's global teardown config value.
Here's the situation: my app creates a database connection. It also has a destroy
method that closes the database connection. This works.
I have a single test that starts the server, runs a query against the database connection. In my global teardown function, I call app.destroy()
, but the process hangs.
If I comment out the destroy
call in the global teardown function and put app.destroy()
in my test after the query, Jest doesn't hang and closes like it's supposed to. I can also put afterAll(() => app.destroy())
in my test file and things work properly.
Here is my jest.config.js
module.exports = {
testEnvironment: 'node',
roots: [
'<rootDir>/src'
],
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: [
'ts',
'tsx',
'js',
'jsx',
'json',
'node'
],
globalSetup: '<rootDir>/src/testSetup.ts',
globalTeardown: '<rootDir>/src/testTeardown.ts'
};
Here is the test (it's currently the only test in the app):
import app from '../..';
describe('User router', () => {
it('Should respond with an array of user objects', async () => {
await app.models.User.query();
});
});
And here is the global teardown in <rootDir>/src/testTeardown.ts
:
import app from './index';
module.exports = async function testTeardown() {
await app.destroy();
};
Using the code above, the process hangs after tests finish. I've tried adding a console.log
to testTeardown
and the end of the test, and the logs happen in the correct order: test logs, then teardown logs. However if I move app.destroy()
into my test it works perfectly:
import app from '../..';
describe('User router', () => {
it('Should respond with an array of user objects', async () => {
await app.models.User.query();
await app.destroy();
});
});
This also works:
import app from '../..';
afterAll(() => app.destroy());
describe('User router', () => {
it('Should respond with an array of user objects', async () => {
await app.models.User.query();
});
});
Why is this happening?
Also just for shits and giggles I tried setting a global._app
in the test and then checking it in the teardown handler, but it was undefined
. Do Jest's setup/teardown functions even get run in the same process as the tests?
No, jest globalSetup and globalTeardown files don't necessarily get run in the same process as your tests. This is because jest parallelises your tests and runs each test file in a separate process, but there is only one global setup/teardown phase for the combined set of test files.
You can use setupFiles
to add a file that gets run in process with each test file. In the setupFiles
file you can put:
afterAll(() => app.destroy());
Your jest config is just
module.exports = {
testEnvironment: 'node',
roots: [
'<rootDir>/src'
],
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: [
'ts',
'tsx',
'js',
'jsx',
'json',
'node'
],
setupFiles: ['<rootDir>/src/testSetup.ts']
};
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