Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing synchronous code

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:

  • using done() instead of returning a promise
  • replacing node-sync with synchronize.js
  • increasing timeout

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.

like image 580
Konrad Dzwinel Avatar asked Jun 06 '15 12:06

Konrad Dzwinel


People also ask

How do you test asynchronous?

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.

How do you test asynchronous code in Jest?

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.

What is synchronous and asynchronous testing?

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.


2 Answers

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.

like image 124
Wilson Avatar answered Sep 28 '22 00:09

Wilson


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

like image 35
beautifulcoder Avatar answered Sep 27 '22 23:09

beautifulcoder