How to test a clustered Express app with Mocha?
express, node.js
Solution
It's been quite a long time since I have posted this question. Since no one has answered, I will answer to this question myself.
I kept the /index.js as it is:
module.exports = process.env.CODE_COV
? require('./lib-cov/app')
: require('./lib/app');
In /lib/app.js which starts the cluster, I have the following code. In brief, I start the cluster only in non-test environment. In test environment the cluster is not started but only one app/worker itself is started as defined in the `cluster.isMaster && !module.parent.parent` condition.
var cluster = require('cluster'),
express = require('express'),
app = module.exports = express.createServer();
if (cluster.isMaster && !module.parent.parent) {
// Considering I have 4 cores.
for (var i = 0; i < 4; ++i) {
cluster.fork();
}
} else {
// do app configurations, then...
// Don't listen to this port if the app is required from a test script.
if (!module.parent.parent) {
app.listen(8080);
}
}
In the above case `!module.parent.parent` will be evaluated as a truthful object only if the application was not started by a test script.
- `module` is the current /lib/app.js script.
- `module.parent` is its parent /index.js script.
- `module.parent.parent` is `undefined` if the application was started directly via `node index.js`.
- `module.parent.parent` is the test script if the application was started via one of the scripts.
Thus, I can safely start the script where I can set a custom port.
/test/test1.js
var app = require('../');
app.listen(7777);
// send requests to app, then assert the response.
At the same time if I need to run the application in real, i.e. not for testing, then I run `node index.js` and it will start up the cluster of applications.
Problem
Here is a simplified version of my cluster Express app: /index.js ``` module.exports = process.env.CODE_COV ? require('./lib-cov/app') : require('./lib/app'); ``` /lib/app.js ``` var cluster = require('cluster'), express = require('express'), app = module.exports = express.createServer(); if (cluster.isMaster) { // Considering I have 4 cores. for (var i = 0; i < 4; ++i) { cluster.fork(); } } else { // do app configurations, then... // Don't listen to this port if the app is required from a test script. if (!module.parent.parent) { app.listen(8080); } } ``` /test/test1.js ``` var app = require('../'); app.listen(7777); // send requests to app, then assert the response. ``` Questions: - `var app = require('../');` will not work in this cluster environment. Which of the worker apps should it return? Should it return the cluster object instead of an Express app? - Now, obviously setting the port in the test script will not work. How would you set a port within a test script to a cluster of apps? - How would you send requests to this cluster of apps? The only solution I can think of is to conditionally turn off the clustering feature and run only one app if the app is requested from a test script (`if (module.parent.parent) ...`). Any other way to test a clustered Express app with Mocha?