Неудачный тест - Mocha's done () вызывается несколько раз - PullRequest
2 голосов
/ 31 октября 2019

Я пытался просмотреть темы с похожей ошибкой, но не смог вписать эти решения в контекст моей проблемы.

Когда я пытаюсь запустить следующий тест (включенная функция, которая тестируется):

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

Я получаю эту ошибку: enter image description here В чем причина этого и как я могу это исправить?

Ответы [ 2 ]

0 голосов
/ 31 октября 2019

@ Решение Анкифа Агарвала не было правильным, но оно указало мне правильное направление.

Метод forEach () не имеет короткого замыкания и поэтому вызывает функцию next () более одного раза ( Короткое замыкание Array.forEach, например, вызов прерывания ).

Мне удалось решить эту проблему одним из двух способов.

Извлекая вызов функции next () изЛогика forEach ():

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

Надеюсь, кто-то может использовать это в будущем.

0 голосов
/ 31 октября 2019

Вам необходимо добавить return в блок if вашего myFunc, чтобы функция обратного вызова 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...