How to run tests for your express app asynchronously using Mocha and Chai

OrderStack
3 min readJul 9, 2021

We needed to write some tests for our node application. We had an idea of writing tests with the help of Mocha and Chai, but we hadn’t been able to use them, until just recently. After going through their documentation, we came across a lot of problems, and hence decided to write an article describing our problems and how we tackled them.

Problem faced while writing tests using Mocha

  • The tests command has to be executed right after the server is run.
  • To programmatically write a script to execute the Mocha commands is tricky as the app instance needs to be run first and only after that the test command needs to be executed.
  • The problem with writing a script to execute the Mocha command is that the command always runs before the app instance is executed if the app has any dependencies like a database connection or a microservice.

How to tackle this problem

After going through a lot of documentation, we finally found the documentation of Mocha after going through their GitHub page on how to execute Mocha commands programmatically.

We used fork, a child process of Node which is similar to the spawn() process to execute the Mocha command programmatically. To know more about fork, click here.

Fork helps run a child process and this child process can communicate with the running app instance.

Sample Code to run the tests

Add the below code to your app.js file:

// this is the load function which will help run the child process
load().then(() => {
// start listening
app.listen(port, function () {
logger.info('Listening on ' + port);
// if the process is the child process
if (process.send) {
process.send("ready");
}
});
}).catch((error) => {
console.log("Error while intializing : ", error);
});

Code explanation:

A load function is called to tell the child process that the app server is up and running. This will be in the app.js file.

Sample test code for the tests:

// initialize the fork process
let { fork } = require("child_process");
var Mocha = require("mocha"),
fs = require("fs"),
path = require("path");
// Instantiate a Mocha instance.
var mocha = new Mocha();
// fork a new child process and store it in a variable
var appProc = fork("./app", {});
// Add an event listener to verify if the app is instantiated
appProc.on("message", function (message) {
if (message == "ready") {
console.log("Server Running");
var testDir = "./tests";// Add each .js file to the mocha instance
fs.readdirSync(testDir)
.filter(function (file) {
// Only keep the .js files
return file.indexOf(".js") > -1;
})
.forEach(function (file) {
mocha.addFile(path.join(testDir, file));
});
// Run the tests.
mocha
.run(function (failures) {
appProc.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
process.exit(failures ? 1 : 0);
})
.on("end", function () {
console.log("Tests finished");
});
}
});
// log an error if an error has occured
appProc.on("error", function (err) {
console.error("Error occured on the server", err.message);
process.exit(1);
});
// log an error if the server exited
appProc.on("exit", function () {
var msg = "Server exited before tests";
console.error(msg);
process.exit(1);
});
// to gracefully kill the process
appProc.on("SIGTERM", function () {
process.exit(1);
});

Code Explanation:

We have to first initialize the fork process and also Mocha and other required node packages like fs, path and Chai. We then have to fork the app.js file to check if the app is running. The fork process has an event listener which listens to the message passed when the app instance is up and running. In our case, as you can see, the load function in the app.js file returns

message = “ready” 

when the app instance has started. We then have to just loop through the files in the tests folder and run the individual tests.

To refer to the Mocha documentation, click here.
To refer to the Mocha GitHub documentation, click here.
To refer to the Chai documentation, click here.

We try to help the coding community by posting new articles frequently. If you like our articles please give us a clap! :) In our next article we will be discussing about how to make a clean and lean express app.

If you have any queries or think that we missed out on something you wanted, feel free to message us on our social media handles:

Facebook: OrderStack
Instagram:
orderstack
Twitter:
@orderstack

--

--

OrderStack

At OrderStack, we bring to you an augmented tech team that sells engineering as a service! We work with start-ups to build bespoke MVPs.