I'm getting this message every time i'm using any libraries that depend on promises.
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles
to troubleshoot this issue.
I have a function that need to make a request to external api, and in the same method just save in the database without waiting for a response.
I don't want to wait until the saving process is done, but i'm forced to change the behaviour of my application to get it tested through jest., or i need to close the connection, stop the server for my code to work.
Excecpted jest to stop and return to my console.
test("it should create new order", async () => {
const response = await server.inject({
method: "POST",
url: "/api/orders",
payload: JSON.stringify({
customer: {
email: "[email protected]",
phone: "20 51 75 95",
city: "Aarhus",
zip: "8000",
first_name: "jamal",
last_name: "soueidan"
},
properties: [
{
name: "custom engraving",
value: "Happy Birthday Mom!"
}
]
})
});
expect(response.statusCode).toBe(200);
});
I had to make those changes to get jest working with my api server and mongodb.
https://github.com/jamalsoueidan/giv-et-tilbud/commit/d8f326b6294f88d1f12136042d4adfdc83328201
npx envinfo --preset jest
System:
OS: Windows 10
CPU: x64 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
Binaries:
npm: 6.4.1 - C:\Program Files\nodejs\npm.CMD
Try putting "done" inside the callback from the test function as so:
const whateverYouExpect = 123;
test('some description of test', async (done) => {
await someAsyncTask();
await secondAsyncTask();
evenCallbacksCanWork((result) => {
expect(result).toBe(whateverYouExpect);
done();
});
})
Additionally, if a connection is being kept open, this will also stop the test from completing, so closing any open connection would be recommended as well.
Thank you ExoMemphiz, but this callback, from where should I reachit?
It's too deep inside the server.
I moved to Ava, it works out of the box ๐
Well well, my danish brother :)
The problem is that I'm using mongoose to save something async when I call this api, and I cannot reach this code to figure out when it's finished saving the document inside mongo.
await server.inject
The code above actually wait for the response only, and it works, but jest complain about the mongoose save, it still in progress saving behind the scene.
I tried to disconnect mongoose, and close each connection, but it doesn't work.
I was getting the same error in one of my integration tests. In it, I was using a Sequelize Model to setup the database to a known state in beforeAll
or beforeEach
. The fix was to call close
on the Sequelize instance connected to the Model in the afterAll
callback. Hope this helps someone else.
EDITED:
And by popular request, here is effectively what I've done:
# dbConnection.js
export default new Sequelize({...}); // The Sequelize instance.
# some.spec.js
import dbConnection from './dbConnection';
const { SomeModel } = dbConnection.models;
describe('...', () => {
beforeEach(async () => {
await SomeModel.create({...});
});
...
});
afterAll(async done => {
// Closing the DB connection allows Jest to exit successfully.
dbConnection.close();
done();
});
@Shrikant9
@AnitaMartinez
I added an example.
I was getting the same error in one of my integration tests. In it, I was using a Sequelize Model to setup the database to a known state in
beforeAll
. The fix was to callclose
on the Sequelize instance connected to the Model in theafterAll
callback. Hope this helps someone else.
What version of Sequelize are you using? I get sequelizeInstance.close()
is not a function.
I was getting the same error in one of my integration tests. In it, I was using a Sequelize Model to setup the database to a known state in
beforeAll
. The fix was to callclose
on the Sequelize instance connected to the Model in theafterAll
callback. Hope this helps someone else.
Can you show your code?
Hi, I was getting the same error, with @dhurlburtusa tip, my code was @AnitaMartinez, I'm new in TypeScript, so I'm pretty sure this can be done in a better way:
let conn: Connection;
const createGlobalDatabaseConnection = (fn: Function) => dbConnection().then((conn: Connection) => fn(conn));
createGlobalDatabaseConnection((connection: Connection) => {
conn = connection;
});
const closeGlobalDatabaseConnection = async () => {
await conn.close();
}
afterAll(async () => {
await closeGlobalDatabaseConnection();
});
The dbConnection
Promise is the function that actually connects to the database instance.
I was getting the same error in one of my integration tests. In it, I use mongo
. The fix was to call close on the mongoose.connection
. Hope this helps someone else.
const mongoose = require('mongoose')
describe(' ...... ', ()=>{
afterAll( async () =>{
await mongoose.connection.close()
})
})
Had this problem with tests that used firebase. This fixed it:
beforeAll(async () => {
await firebase.firestore().enableNetwork();
});
afterAll(async () => {
await firebase.firestore().disableNetwork();
});
If you've multiple test files, I use global setup and teardown. For example in jest.config.js
I defined:
module.exports = {
globalSetup: './setupTests.js',
globalTeardown: './teardownTests.js',
};
In setupTests
I connect to the db and return a function which returns a promise. Similarly in teardownTests
I close the db connection and return a function which returns a promise.
I was having this problem with Knex and using global setup and teardown files on Jest.
My solution was:
// setup.js
const knexConfiguration = require('../config/knex')[process.env.NODE_ENV];
const knex = require('knex');
const setup = async () => {
const client = knex(knexConfiguration)
await client.migrate.latest();
await client.destroy();
};
module.exports = setup;
// teardown.js
const knexConfiguration = require('../config/knex')[process.env.NODE_ENV];
const knex = require('knex');
const teardown = async () => {
const client = knex(knexConfiguration)
await client.migrate.rollback();
await client.destroy();
};
module.exports = teardown;
Hope it helps anybody facing this kind of problem.
Hello everyone,
Please correct me if I'm wrong but this seems like an issue which is not on Jest's side.
If you want the tests to exit even when there are external resources being held I think you should use --forceExit
. The forceExit
flag is specifically designed for this case and therefore is an indication that tests not exiting when it's not present is indeed an expected behaviour and not a bug.
Force Jest to exit after all tests have completed running. This is useful when resources set up by test code cannot be adequately cleaned up. Note: This feature is an escape-hatch. If Jest doesn't exit at the end of a test run, it means external resources are still being held on to or timers are still pending in your code. It is advised to tear down external resources after each test to make sure Jest can shut down cleanly.
As the author mentioned, it's possible to use --detectOpenHandles
for debugging this (and this is also mentioned in the docs btw).
Given the arguments above, perhaps this issue could be closed?
@lucasfcosta Every time I've tried using --detectOpenHandles
in my test code in a few different applications over the years it has never provided me with any useful output. It just sits there waiting for everything to wrap up but without printing the warning that suggests to use the argument in the first place. Is there some trick to getting useful output from that argument that I am unaware of?
Is there any other way to debug? --detectOpenHandles
is not showing any output. Thanks
Same here. I get no output from --detectOpenHandles
.
$ yarn test:types && jest --config ../../jest.config.js --detectOpenHandles
$ tsc --noEmit
PASS src/App.test.tsx (9.447s)
โ renders without crashing (240ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.201s, estimated 14s
Ran all test suites.
(node:9784) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1126:14)
(node:9784) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a prom
ise which was not handled with .catch(). (rejection id: 2)
(node:9784) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-z
ero exit code.
My jest.config.js:
module.exports = {
bail: true,
collectCoverage: false,
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/index.tsx', '!src/main.ts', '!**/node_modules/**'],
coverageDirectory: '<rootDir>/coverage',
coverageThreshold: {
global: {
branches: 100,
functions: 100,
lines: 100,
statements: 100,
},
},
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx'],
rootDir: process.cwd(),
testMatch: ['<rootDir>/src/**/*.test.{ts,tsx}'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
verbose: true,
};
My test case:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
For anyone running into this using sequelize
, I had to do this:
afterAll(async done => {
await models.sequelize.close();
done();
});
That fixed the issue.
I'm testing Jest with mongoose and supertest, add testEnvironment: 'node'
fixed this issue for me.
Another possible reason I faced โ not closed Redis connection.
afterAll(async done => {
globalRedisClient.unref();
done();
});
My solution won't work for everyone, but if you scoured the web for as long as I did trying to figure out how to close that damn handle that was left open, this might help. In my ecosystem, we are running a Parse Server as middleware with an Express server, but this could apply to anyone who needs to run a separate server with the tests but is unable to close some socket or port at the end. I _believe_ the issue causing the dreaded "Jest did not exit one second..." error for us was a result of Parse's MongoDB adapter not closing correctly.
So to get around this issue, I abstracted the server initialization completely out of the jest test suite and created a special npm script to run it in an entirely separate process.
NPM Script (package.json):
"scripts": {
"test": "npm start & ./listen_on_port_5000.sh && jest test && kill $(lsof -t -i tcp:5000)",
}
listen_on_port_5000.sh
while ! nc -z localhost 5000
do
sleep 0.5
done
So how does this work?
npm start
runs which is the normal command we would run to start our server with Express and Parse.start
script in the background and start a separate process running a shell script (listen_on_port_5000.sh
) to wait for the server to boot up.jest
command (all while the Express server is up and running).kill
script to close the server running on port 5000.I had tests that were checking auto generated http server and socket.io connections.
The tests were running fine on my windows machine, but failing for not exiting on my Jenkins server.
I was closing both the socket.io server and http server correctly at the end of the test, but I was not closing the clients. Once I added the cleanup for the clients, the tests exited successfully on their own on both my dev machine and CI server.
The tests would work without closing the clients if I used --forceExit
, but at the end of the day, the real problem was improper cleanup.
I also found that --detectOpenHandles
did not produce any output.
I have run into the same issue with globalSetup
and globalTeardown
hooks, but I can't find any processes left unattended. I added done()
to the end of all the tests, and I am stopping my server during teardown.
jest --runInBand --detectOpenHandles
doesn't print anything to the console.
I have run into the same issue with
globalSetup
andglobalTeardown
hooks, but I can't find any processes left unattended. I addeddone()
to the end of all the tests, and I am stopping my server during teardown.
jest --runInBand --detectOpenHandles
doesn't print anything to the console.
Facing same issue tried closing sequelize connection , no luck there.
Even though the issue might not be with jest but its main problem is it doesn't display which processes are active --detectOpenHandles
doesn't print anything :confused:
On the top if we use --forceExit it shows message to use --detectOpenHandles
Irony :-1:
I've been having this problem too
I ended up using https://www.npmjs.com/package/why-is-node-running logging in beforeAll
import log from 'why-is-node-running';
afterAll(async () => {
//normal cleanup things
await new Promise(resolve => {
setTimeout(() => {
log()
resolve()
}, 4000)
})
}
turns out that since I was using jest.resetModules, I had to reimport the module that was using a pg connection and close it there too.
I'm also having this problem. To give some context, I am using SuperTest to do some e2e testing with MongoMemoryServer
.
My setup and teardown looks like this:
let mongoServer;
beforeAll(async (done) => {
mongoServer = new MongoMemoryServer({ instance: { port: 26016 } });
const uri = await mongoServer.getUri();
process.env.MONGODB_URI = uri;
done();
});
afterAll(async (done) => {
await mongoServer.stop();
done();
});
Nothing out of the ordinary that would suggest that I'm following the documentation wrong.
I started troubleshooting by looking at Activity Monitor
on MacOS. It seems that there are two node
processes that are still running whilst jest is running.
However, as soon as I cancel / quit the test run, the processes also quit.
I'm going to investigate further by sampling the node processes and see exactly what spawns them. I will update here with my findings.
EDIT: Related issue #1456 - it looks like it's an underlying NodeJS issue. tl;dr - add the --forceExit
flag to your test script in package.json
Hello! It seems like you haven't yet disconnect to the database. I've been try mongoose.disconnect()
in afterAll()
function and it don't show message like that anymore.
@BigsonLvrocha thank you for that idea re: why-is-node-running
! In my case that tool showed me that redux-state-sync
was being initialized in tests, which has an infinite loop to listen for Redux updates in it. --detectOpenHandles
did not output anything for me, either.
I am testing my React Native app and getting this. I am fetching data from BE and use moxios
. Then I dispatch an action to update the store. I am using "jest": "^26.4.2",
test('dispatch paperPlanes/set action correctly updates the store', async done => {
// Mock the response to /paperPlane/list
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: expectedResponse,
});
});
// Execute the api call to /paperPlane/list
const res = await axios.get('/paperplane/list');
const action = actionCreators.paperPlanes.set(res.data.paper_planes);
store.dispatch(action);
const newState = store.getState();
expect(newState.paperPlanes.paperPlanes).toEqual(
expectedResponse.paper_planes,
);
done();
});
I am having this error on several jest tests. I am closing express server properly with server.close().
On a test i solved the problem closing a mongoose connection properly using connection.disconnect().
But other tests are presenting the message yet. I noticed that all my tests that uses the supertest package keeps the message.
The way is to analyze case by case.
What if I'm not calling a database ? What if I'm calling an external resource of which I have no control ? How do I "close" ?
@YounesTea you might have an async/await call in your code.
Try calling done()
after you're, well, done ๐
it("Should test something", async (done) => {
// Sends request...
const req = await request(app).get("/someEndpoint");
expect(req).toBeTruthy();
done();
});
@YounesTea you might have an async/await call in your code.
Try callingdone()
after you're, well, doneit("Should test something", async (done) => { // Sends request... const req = await request(app).get("/someEndpoint"); expect(req).toBeTruthy(); done(); });
I have async/awaits and i am already using the done() callback on the tests including beforeAll and afterAll.
The problem persists...
beforeAll(async () => {
await firebase.firestore().enableNetwork();
});afterAll(async () => {
await firebase.firestore().disableNetwork();
});
That doesn't work. However, this one works:
afterAll(async () => {
await app.delete()
})
in mongo i solved this:
`afterAll(async(done) => {
// Closing the DB connection allows Jest to exit successfully.
await mongoose.connection.close()
done()
})`
Most helpful comment
I was getting the same error in one of my integration tests. In it, I was using a Sequelize Model to setup the database to a known state in
beforeAll
orbeforeEach
. The fix was to callclose
on the Sequelize instance connected to the Model in theafterAll
callback. Hope this helps someone else.EDITED:
And by popular request, here is effectively what I've done:
@Shrikant9
@AnitaMartinez
I added an example.