Reputation: 795
I'm trying to test routes in my express app. App.js is a subapp, when it runs it waits for DB connection and then mounts the routes based on the result.
app.js
db.connect() // returns a promise
.then(dbConnection => {
app.use(routes(dbConnection));
app.emit('dbConnected'); // DB Connected
}).catch(error => {
// if db connection fails - return 503 for every request
console.log(`DB connection failed.`);
app.use((req, res, next) => {
const error = new Error('Service unavailable');
error.statusCode = 503;
error.name = err.name;
next(error)
});
});
module.exports = app;
I've written the app.test.js to test the routes. I want the tests to wait until the connection is established (because only then the routes are mounted).
app.test.js
before(function (done) {
app.on('dbConnected', () => done());
});
// tests go here...
The problem is that the 'dbConnected' event is not always caught by the event handler in app.test.js and I get ELIFECYCLE error.
1) "before all" hook: Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
The tests sometimes run correctly, therefore I'm assuming that this is a problem with how I handle the 'dbConnected' event. I'd like to know how to approach this problem properly.
Upvotes: 0
Views: 1638
Reputation: 418
It might be a race condition - it's possible that the DB got connected before the test started. In such a case you'll never get the event because it has already fired.
I would check if the DB is connected and only if it isn't I'll wait for the 'dbConnect' event. Something like
before(function (done) {
if (app.isDbConnected) { // set app.isDbConnected when connected.
process.nextTick(done)
} else {
app.on('dbConnected', () => done());
}
});
Upvotes: 1