测试失败 - 多次调用 Mocha 的 done()

Failing test - Mocha's done() called multiple times

我尝试查看有类似错误的主题,但无法将这些解决方案纳入我的问题的上下文。

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

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 }
    ]
  });
});

我收到这个错误: 这是什么原因造成的,我该如何解决?

您需要在 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();
}

@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);
  }
}

希望以后有人能用上这个。