测试同步代码

时间:2015-06-06 12:49:08

标签: node.js mocha

我有一段使用node-sync的代码,如下所示:

function funcA() {
  return new Promise(function(resolve, reject) {
    Sync(function () {
      return funcB.sync();
    }, function (err, result) {
      if(err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
}

此代码使用mocha + chai进行测试:

it("should return array", function() {
  return funcA().then(function(result) {
    expect(result).to.be.an.instanceof(Array);
  });
});

几个月前它工作得很好,但现在这个测试总是超时:

  

错误:超过2000毫秒的超时。确保在此测试中调用done()回调。

到目前为止我尝试过:

  • 使用done()而不是返回承诺
  • node-sync替换为synchronize.js
  • 增加超时

我发现,这个测试的expect(...部分实际上是被调用的,但只有在mocha杀死测试之后。无论当前设置了什么超时间隔,我都会在收到expect(..消息后约20毫秒内调用Error: timeout

我通过在测试文件的顶部添加setInterval(function(){}, 10)来修复此问题。 我想知道为什么会有效,如果有更好的方法可以解决这个问题?

[编辑]看起来这是特定于节点版本的问题。测试在0.12.4上失败,但在0.10.38上正确运行。

[编辑]实际代码可用here

3 个答案:

答案 0 :(得分:2)

根据您的code,我假设您的funcB功能以同步方式运行代码

所以当我以这种方式创建funcB时:

function funcB() {
  return [1, 2, 3];
}

运行测试,Mocha显示错误:

  

错误:超过2000毫秒的超时。确保在此测试中调用done()回调。

但如果我将 asynchronus函数中的funcB转换为:

function funcB(cb) {
  process.nextTick(function () {
    cb(null, [1, 2, 3]);
  });
}

Mocha毫无问题地运行测试:

  

✓应该返回一个数组

所以我的完整代码运行正常(funcB评论是导致错误的代码)是这样的:

// 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();
    }
  );
});

所以我认为我认为同步库创建的sync method(在同步函数上使用它)被滥用导致了这个问题。

答案 1 :(得分:1)

您可能只是错过了done()回调:

it("should return array", function(done) {
    funcA().then(function(result) {
        expect(result).to.be.an.instanceof(Array);
        done();
    });
});

http://mochajs.org/#asynchronous-code

答案 2 :(得分:1)

You can use a timeout parameter for mocha executable.

For example, if you want a 500 milliseconds timeout, just change your package.json to:

"scripts": {
    "test": "mocha specs --timeout 500 --require specs/helpers/chai.js"
},

And maybe your promise is being rejected, so you have to call done using catch method.

it("should return array", function(done) {
    return funcA().then(function(result) {
        expect(result).to.be.an.instanceof(Array);
        done();
    }).catch(done);
});

This would also help you debug eventual errors that might happen in your promise code.