I want to test a asynchronous javascript function that runs in node.js and makes a simple request to a http api:
const HOST = 'localhost';
const PORT = 80;
http = require('http');
var options = {
host: HOST,
port: PORT,
path: '/api/getUser/?userCookieId=26cf7a34c0b91335fbb701f35d118c4c32566bce',
method: 'GET'
};
doRequest(options, myCallback);
function doRequest(options, callback) {
var protocol = options.port == 443 ? https : http;
var req = protocol.request(options, function(res) {
var output = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log(chunk);
output += chunk;
});
res.on('error', function(err) {
throw err;
});
res.on('end', function() {
var dataRes = JSON.parse(output);
if(res.statusCode != 200) {
throw new Error('error: ' + res.statusCode);
} else {
try {
callback(dataRes);
} catch(err) {
throw err;
}
}
});
});
req.on('error', function(err) {
throw err;
});
req.end();
}
function myCallback(dataRes) {
console.log(dataRes);
}
Executed this code works and the response will be displayed as expected.
If I execute this in a mocha test the request is not executed:
describe('api', function() {
it('should load a user', function() {
assert.doesNotThrow(function() {
doRequest(options, myCallback, function(err) {
if (err) throw err;
done();
});
});
assert.equal(res, '{Object ... }');
});
});
The Problem is, that no code after:
var req = protocol.request(options, function(res) {
is executed not even a simple console.log.
Can anybody help?
You have to specify the callback
done
as the argument to the function which is provided to mocha - in this case theit()
function. Like so:Also, the signature of
doRequest(options, callback)
specifies two arguments though when you call it in the test you provide three.Mocha probably couldn't find the method
doRequest(arg1,arg2,arg3)
.Did it not provide some error output? Maybe you can change the mocha options to get more information.
EDIT :
andho is right, the second assert would be called in parallel to
assert.doesNotThrow
while it should only be called in the success callback.I have fixed the example code.
EDIT 2:
Or, to simplify the error handling (see Dan M.'s comment):
I've done a very similar test in my project for an http client. I paste the code here and hope is useful. Here is the client (my nodejs server use express and I use promise for error handling):
And here is the test:
If you have an asynchronous function that does not support callbacks, or if you think using unnecessary callbacks is... unnecessary, then you can also just turn the test into an async test.
instead of:
simply do:
Now you can
await
async functions: