Should tearDown be queued on process.nextTick?
I've encountered an issue that's reproducible with async.parallel/auto and nodeunit.
var async = require('async');
var str;
exports.setUp = function(cb){
console.log('setup');
str = "This is a test";
cb();
}
exports.tearDown = function(cb){
//process.nextTick(function(){
console.log('teardown');
str = undefined;
cb();
//});
}
exports["testA"] = function(test){
async.auto({
test1:function(cb, results){
console.log('test1');
cb(new Error("test"));
},
test2:function(cb, results){
console.log('test2');
console.log(str, str.length);
cb();
}
}, function(err, results){
if(err) console.error(err);
test.done();
});
}
exports["testB"] = function(test){
async.parallel({
test1:function(cb, results){
console.log('test1');
cb(new Error("test"));
},
test2:function(cb, results){
console.log('test2');
console.log(str, str.length);
cb();
}
}, function(err, results){
if(err) console.error(err);
test.done();
});
}
This produces the output:
setup test1 [Error: test] teardown test2 teardown ✖ testA
TypeError: Cannot read property 'length' of undefined at Array.exports.testA.async.auto.test2 as 0 at async.auto (/Users/davefenster/node_modules/async/lib/async.js:406:38) at Array.forEach (native) at _forEach (/Users/davefenster/node_modules/async/lib/async.js:26:24) at Object.async.auto (/Users/davefenster/node_modules/async/lib/async.js:382:9) at Object.exports.testA (/Users/davefenster/temp/testnodeunitbug/test.js:19:8) at wrapTest (/Users/davefenster/node_modules/nodeunit/lib/core.js:231:20) at _asyncMap (/Users/davefenster/node_modules/nodeunit/deps/async.js:163:13) at async.forEachSeries.iterate (/Users/davefenster/node_modules/nodeunit/deps/async.js:126:25) at _asyncMap (/Users/davefenster/node_modules/nodeunit/deps/async.js:160:17)
setup test1 [Error: test] teardown test2 teardown ✖ testA
TypeError: Cannot read property 'length' of undefined at Array.exports.testA.async.auto.test2 as 0 at async.auto (/Users/davefenster/node_modules/async/lib/async.js:406:38) at Array.forEach (native) at _forEach (/Users/davefenster/node_modules/async/lib/async.js:26:24) at Object.async.auto (/Users/davefenster/node_modules/async/lib/async.js:382:9) at Object.exports.testA (/Users/davefenster/temp/testnodeunitbug/test.js:19:8) at wrapTest (/Users/davefenster/node_modules/nodeunit/lib/core.js:231:20) at _asyncMap (/Users/davefenster/node_modules/nodeunit/deps/async.js:163:13) at async.forEachSeries.iterate (/Users/davefenster/node_modules/nodeunit/deps/async.js:126:25) at _asyncMap (/Users/davefenster/node_modules/nodeunit/deps/async.js:160:17)
FAILURES: 2/2 assertions failed (12ms)
FAILURES: Undone tests (or their setups/teardowns):
- testB
To fix this, make sure all tests call test.done()
The error manifests itself because tearDown runs before all the async.auto and async.parallel functions have executed. Ideally, what I'd want is the tearDown to run only after async.auto/parallel are complete. To make the tests pass, uncomment the process.nextTick line in the tearDown function.
Should nodeunit be putting tearDown on the nextTick queue all the time?