Laurence Laurence - 5 months ago 75
Node.js Question

Assert not working in mocha when using child_process exec

I have some troubles with unit testing code that uses a module that uses child_process exec. Mocha does not work properly when I create an unit test that uses asserts inside or after an exec call. When an assert is triggered, Mocha just will keep running until the given timeout is reached. When the assert is not triggered, everything will work properly.

For example, in this test case Mocha will run until the timeout is reached:

it('someTest', function (done) {
var exec = require('child_process').exec;
exec('ping 8.8.8.8', () => {
assert.deepEqual(1, 2, 'test');
done();
});
});


Then same problem still accrues when the assert is outside the exec:

it('someTest2', function (done) {
var exec = require('child_process').exec;
var promise = new Promise((promiseDone) => {
exec('ping 8.8.8.8', () => {
var success = 1 === 2;
promiseDone(success, '1 has to be 2');
});
});
promise.then((success, message) => {
assert.deepEqual(success, true, message); // Assert stops the test but Mocha does not stop
done();
});
});


A workaround for this problem is to create a before statement where you execute the method that uses exec and save the results, then you create a it(); block that checks those results with asserts.

This does not feel like a proper solution. With this approach, you are doing the unit tests in a before statement and check the results later in an it(); block. That cannot be right.

An example:

var success = true;
before(function (done) {
this.timeout(10000);
var exec = require('child_process').exec;
exec('ping 8.8.8.8', () => {
success = 1 === 2;
done();
});
});

it('someTest1', function (done) {
assert.deepEqual(success, true, 'test');
done();
});

Answer

Your ping command takes longer than 2 seconds. I'm not all that familiar with Windows but the attempts that ping makes by default take longer than 2 seconds. So increasing the timeout is one solution.

On a *nix system ping will typically run until you hit Ctrl-C. According to the man on my Debian system, if you want ping to end earlier, you can use -c [count] to set the number of packets to send. Or -w [deadline] to set a deadline by which it must end. For instance, ping -w 1 8.8.8.8 will work just fine with your code. (There's also -W [timeout] which tells ping how long to wait before giving up if there is no response, see the manual for details.)

If you were just using ping as some placeholder command just to test the structure of your Mocha tests, you could use echo foo instead (or whatever the equivalent is on Windows), or something as simple that ends right away.

Comments