【问题标题】:Failing test - Mocha's done() called multiple times测试失败 - 多次调用 Mocha 的 done()
【发布时间】:2019-10-31 07:36:26
【问题描述】:

我已尝试查看具有类似错误的主题,但无法将这些解决方案适合我的问题。

当我尝试运行以下测试时(包含的测试功能):

function myFunc(next, obj) {
  const pairs = {};
  obj.listing.forEach((element) => {
    if (element.x in pairs && pairs[element.x] !== element.y) {
      const err = new Error('This was not ok');
      next(err);
    } else {
      pairs[element.x] = element.y;
    }
  });
  next();
}

it('should fail as 9 has been changed to 5 in the second object of the listing', function (done) {
  const callback = (err) => {
    if (err && err instanceof Error && err.message === 'This was not ok') {
      // test passed, called with an Error arg
      done();
    } else {
      // force fail the test, the `err` is not what we expect it to be
      done(new Error('Assertion failed'));
    }
  }
  myFunc(callback, {
    "listing": [
      { "x": 5, "y": 9 },
      { "x": 5, "y": 11 }
    ]
  });
});

我收到此错误: 这是什么原因,我该如何解决?

【问题讨论】:

    标签: javascript unit-testing callback mocha.js


    【解决方案1】:

    您需要在您的myFuncif 块中添加一个return,以便只调用一次回调函数next,并且确实在主测试用例中调用done() 回调:

    function myFunc(next, obj) {
      const pairs = {};
      obj.listing.forEach((element) => {
        if (element.x in pairs && pairs[element.x] !== element.y) {
          const err = new Error('This was not ok');
          return next(err);
        } else {
          pairs[element.x] = element.y;
        }
      });
      next();
    }
    

    【讨论】:

    • 我刚试过这个(也试过在对 next() 的两个调用中添加一个返回),但它仍然抛出同样的错误。
    • 您的回答确实将我推向了正确的方向。我刚刚发布了问题的解决方案。
    【解决方案2】:

    @Ankif Agarwal 的解决方案不是正确的,但它确实为我指明了正确的方向。

    forEach() 方法没有短路,因此多次调用 next() (Short circuit Array.forEach like calling break)。

    我能够以两种方式之一解决这个问题。

    通过从 forEach() 逻辑中提取对 next() 的调用:

    function myFunc(next, obj) {
      const pairs = {};
      let err = null;
      obj.listing.forEach((element) => {
        if (element.x in pairs && pairs[element.x] !== element.y) {
          err = new Error('This was not ok');
        } else {
          pairs[element.x] = element.y;
        }
      });
    
      if (err !== null) {
        next(err);
      } else {
        next();
      }
    }
    

    但是,这仍然会使 forEach() 遍历所有元素。如果可能的话,最好将其短路并在发生设置错误的违规行为时立即将其断开,如下所示:

    function myFunc(next, obj) {
      const pairs = {};
      const BreakException = {};
      let err = null;
      try {
        obj.listing.forEach((element) => {
          if (element.x in pairs && pairs[element.x] !== element.y) {
            err = new Error('This was not ok');
            throw BreakException;
          } else {
            pairs[element.x] = element.y;
          }
        });
        next();
      } catch (e) {
        if (e !== BreakException) throw e;
        next(err);
      }
    }
    

    希望将来有人可以使用它。

    【讨论】:

      猜你喜欢
      • 2020-05-17
      • 1970-01-01
      • 2013-02-04
      • 1970-01-01
      • 2018-04-25
      • 2017-10-04
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      相关资源
      最近更新 更多