I have a section of code that is using node-sync like so:
function funcA() {
return new Promise(function(resolve, reject) {
Sync(function () {
return funcB.sync();
}, function (err, result) {
if(err) {
reject(err);
} else {
resolve(result);
}
});
}
This code is tested using mocha+chai:
it("should return array", function() {
return funcA().then(function(result) {
expect(result).to.be.an.instanceof(Array);
});
});
It worked just fine couple of months ago, but now this test always times out:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
What I've tried so far:
done()
instead of returning a promisenode-sync
with synchronize.js
What I found out, is that expect(...
part of this test is, in fact, being called, but only after mocha kills the test. No matter what timeout interval is currently set, expect(..
is being called always ~20 milliseconds after I get Error: timeout
message.
I fixed the issue by adding setInterval(function(){}, 10)
on the top of the test file. I'd like to know why this worked and if there is some better way to fix that?
[EDIT] It looks like this is a node-version specific issue. Test fails on 0.12.4 but runs correctly on 0.10.38 .
[EDIT] Actual code is available here.
To test asynchronous code, we use the XCTestExpectation class and wait for the expected outcome. The workflow is to create an expectation, and then when the asynchronous task completes successfully, we fulfil that expectation. We will wait for a specific amount of time for the expectation to be fulfilled.
There is an alternate form of test that fixes this. Instead of putting the test in a function with an empty argument, use a single argument called done . Jest will wait until the done callback is called before finishing the test.
In synchronous operations tasks are performed one at a time and only when one is completed, the following is unblocked. In other words, you need to wait for a task to finish to move to the next one. In asynchronous operations, on the other hand, you can move to another task before the previous one finishes.
Based on your code, I am assuming that your funcB function is running code in a synchronous way.
So when I create funcB in this way:
function funcB() {
return [1, 2, 3];
}
And run the test, Mocha shows an error:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
But if I convert the funcB in asynchronus function as this:
function funcB(cb) {
process.nextTick(function () {
cb(null, [1, 2, 3]);
});
}
Mocha runs the test without any problem:
✓ should return an array
So my complete code that runs ok (the funcB commented is the one that will cause the error) is this:
// install dependencies
// npm install promise
// npm install sync
var Promise = require('promise');
var assert = require('assert');
var Sync = require('sync');
function funcA() {
return new Promise(function (resolve, reject) {
Sync(function () {
return funcB.sync();
}, function (err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
// function funcB() {
// return [1, 2, 3];
// }
function funcB(cb) {
process.nextTick(function () {
cb(null, [1, 2, 3]);
});
}
it("should return an array", function(done) {
return funcA().then(
function (result) {
console.log(result);
assert.equal(Array.isArray(result), true);
done();
}
);
});
So I am opinion I think that the misuse of the sync method (using it on synchronous functions) created by sync library is the one that is causing this problem.
You may just be missing the done()
callback:
it("should return array", function(done) {
funcA().then(function(result) {
expect(result).to.be.an.instanceof(Array);
done();
});
});
http://mochajs.org/#asynchronous-code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With