【问题标题】:promise delay in mocha承诺延迟摩卡咖啡
【发布时间】:2017-08-23 20:19:45
【问题描述】:

我目前正在学习诗乃。我的代码:

const bluebird = require('bluebird');
const sinon = require('sinon');
const sinonTest = require('sinon-test')(sinon);

sinon.test = sinonTest;

describe('xxx', function _test() {
  this.timeout(2000);
  it('should', sinon.test(function() {
    return new bluebird.Promise( (resolve, reject) => {
      try {
        console.log('123');
        resolve();
      } catch ( err ) {
        reject(err);
      };      
    })
    .then( () => console.log('456') )
    .delay(100)
    .then( () => console.log('789') )
    .then(function() {
    })
  }));
});

输出:

xxx
    123
    456

为什么上面的代码会超时,卡在delay?谢谢

更新

const bluebird = require('bluebird');
const sinon = require('sinon');
const sinonTest = require('sinon-test')(sinon);

sinon.test = sinonTest;

describe('xxx', function _test() {
  this.timeout(2000);
  it('should', sinon.test(function() {
    return bluebird
    .delay(100)
    .then( () => console.log('789') );
  }));
});

输出:

 Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves

更新

感谢@Louis。设置useFakeTimers 工作正常。

但我只是感到困惑。为什么在我的项目中,useFakeTimers 默认设置为 true 的现有测试没有问题?如果useFakeTimers设置为true,sinonTest()中不能使用promise延迟?

顺便说一句,我在将sinon1.17.6 升级到2.4.1 时遇到了这个问题。 谢谢

【问题讨论】:

    标签: promise mocha.js bluebird sinon


    【解决方案1】:

    默认情况下,Sinon 创建的沙箱具有其配置设置,因此沙箱配置选项 useFakeTimerstrue。 (在这个documentation page中搜索defaultConfig。)

    这意味着当沙盒生效时,时钟似乎停止了,Bluebird 的delay 永远不会解析。您告诉sinon-test 在配置时通过传递第二个参数来创建没有假计时器的沙箱。这第二个参数实际上是 Sinon 沙箱的配置对象:

    const sinonTest = require('sinon-test')(sinon,
                                            { useFakeTimers: false });
    

    我还没有尝试过,但是从观察代码看来,如果您需要一些测试来使用假计时器,而有些测试不使用假计时器,您可以同时使用多个配置:

    const sinonTest = require('sinon-test');
    const wrapper = sinonTest(sinon, { useFakeTimers: false });
    const wrapperWithTimers = sinonTest(sinon);
    

    您只需要使用正确的包装器来满足测试的需要。


    您添加了问题:

    但我只是感到困惑。为什么在我的项目中,useFakeTimers 默认设置为 true 的现有测试没有问题?如果useFakeTimers设置为true,则sinonTest()中不能使用promise延迟?

    默认情况下useFakeTimerstrue,但这不会导致问题,除非您的代码依赖 时钟向前移动才能正常工作。我有许多测试套件,我在其中使用沙盒,并且我没有注意关闭假计时器,它们工作正常。假计时器一般不会阻止异步函数运行。例如,如果您在沙盒生效时执行fs.readFile,它应该可以正常工作。它只会影响依赖时钟的函数,例如setTimeoutsetIntervalDate

    Bluebird 的delay 方法受到影响,因为它calls setTimeout

    【讨论】:

    • 如果{ useFakeTimers: false } 设置,delay 将不起作用?
    • 我将您问题中的代码放入一个新文件中,编辑以添加第二个参数{ useFakeTimers: false },安装所需的软件包并运行 Mocha,它就可以工作了。我得到了所有的console.log 输出并且没有超时。我在写答案之前这样做时它起作用了,现在它起作用了。你一定是做错了什么。
    • 是的。它现在正在工作。你解决了我的几个问题。谢谢。但我只是困惑。为什么在我的项目中,没有设置useFakeTimers的现有测试没有问题?
    • @BAE 我已经在 cmets 中回答了你的最后一个问题,但我删除了 cmets 并编辑了我的答案以在此处添加信息。
    • 所以,delay 不能在it() 内部使用,但可以在before()after() 内部使用?我在之前的测试中使用了很多delay,其中useFakeTimers 设置为true。