Reputation: 2453
I trying to bend my head around the async nature of node.js and nodeunit.
now nodeunit is supposed to help me out but it gives me headaches as well:
$ nodeunit test_logfile.js
test_logfile.js
✖ testLogentry
Error: Expected 1 assertions, 0 ran
at Object.done (/home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/lib/types.js:119:25)
at /home/mark/devel/PerfDriver/test/test_logfile.js:48:10
at Object.runTest (/home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/lib/core.js:54:9)
at /home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/lib/core.js:90:21
at /home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/deps/async.js:508:13
at /home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/deps/async.js:118:13
at /home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/deps/async.js:134:9
at /home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/deps/async.js:507:9
at Object.concatSeries (/home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/deps/async.js:147:23)
at Object.runSuite (/home/mark/.node_libraries/.npm/nodeunit/0.5.1/package/lib/core.js:79:11)
FAILURES: 1/1 assertions failed (50ms)
node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: ECONNREFUSED, Connection refused
at Socket._onConnect (net.js:576:18)
at IOWatcher.onWritable [as callback] (net.js:165:12)
here is my testcase:
var nodeunit = require('../lib/nodeunit/lib/nodeunit.js')
var http = require('http');
var logfile = require('../src/logfile.js');
var testmsg = 'this is my first testmessage:-_,.:;öüäß?1234"@€';
exports.testLogentry = function(test) {
test.expect(1); // make sure all the async expectations are fulfilled
var options = {
host: 'localhost',
port: 8123,
path: '/',
method: 'POST',
record_message: function(msg) {
console.log('received ' + msg + '\n');
test.equal(msg, testmsg);
return;
}
};
var logger = logfile.loggerFactory(options);
logfile.write(testmsg, options);
logger.stop();
test.done();
};
I guess my question is if assertions work well in callbacks or if there are any restrictions that might cause the testcase to fail. My assumption is that nodeunit is able to cope with the asynchronous programming style. So I expect "test.equal(msg, testmsg);" to work. If I run the content of the testcase in the node console then "record_message" is called. I would post logfile.js as well but this is probably to much and I am looking for more general advice.
Thanks.
Mark
Upvotes: 2
Views: 2770
Reputation: 2453
I am not exactly sure how this is handled here generally but meanwhile I have found the solution to my problem and I post it here in case someone will struggle with the same issue.
Now I can tell that the problem has to do with the asynchronous character of node.js, http server and unit testing under these circumstances.
Anyways here is my solution:
var nodeunit = require('../lib/nodeunit/lib/nodeunit.js');
var http = require('http');
var logfile = require('../src/logfile');
var testmsg = 'this is my first testmessage:-_,.:;öüäß?1234"@€';
var testutil = function (config, envReady) {
// simple testutil to provide http server environment for unit testing
var logger = logfile.loggerFactory(config);
// actually this is the tricky part which ensures that the server
// is still available once request/ response are executed
process.nextTick(function () {
if (envReady && typeof envReady === 'function') {
envReady(logger, logfile.write);
}
});
};
exports.test_logfile = function (test) {
test.expect(4);
var options = {
host: 'localhost',
port: 3000,
path: '/simple',
method: 'PUT',
record_message: function(msg) {
test.equal(msg, testmsg);
}
};
testutil(options, function (logger, write) {
var write_ready = function(res) {
// called when write is completed
test.equal(res.statusCode, 201);
test.equal(res.headers['content-type'], 'text/plain');
test.equal(res.body, 'created');
logger.stop();
test.done();
};
write(testmsg, options, write_ready);
});
};
Upvotes: 2
Reputation: 2453
I think in the original version there are a few things wrong. After some hours of sleep I moved the logger.stop() and test.end() calls to the end of the record_message function. Now the assertion "passes" silently but the error is persistent.
$ nodeunit test_logfile.js
test_logfile.js
node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: ECONNREFUSED, Connection refused
at Socket._onConnect (net.js:576:18)
at IOWatcher.onWritable [as callback] (net.js:165:12)
Here is the nodeunit testcase in its current version:
var nodeunit = require('../lib/nodeunit/lib/nodeunit.js')
var http = require('http');
var logfile = require('../src/logfile.js');
var testmsg = 'this is my first testmessage:-_,.:;öüäß?1234"@€';
exports.testLogentry = function(test) {
test.expect(1); // make sure all the async expectations are fulfilled
var options = {
host: 'localhost',
port: 8123,
path: '/',
method: 'POST',
record_message: function(msg) {
console.log('received ' + msg + '\n');
test.equal(msg, testmsg);
logger.stop();
setTimeout(test.done, 2000);
}
};
var logger = logfile.loggerFactory(options);
logfile.write(testmsg, options);
};
Upvotes: 0