Утверждение обратного вызова было вызвано с Jest (без React)? - PullRequest
0 голосов
/ 21 октября 2018

У меня есть набор тестов, но что-то просто не щелкает относительно утверждений обратного вызова.Я чувствую, что параметр done () должен быть вплетен, но я делаю это неправильно.

В основном у меня есть две функциональные структуры, где обратный вызов либо вложен внутри одного оператора тогда, либо затем внутри другого оператора тогда:

function foo(cb) {
   return fetch('foo.com')
          .then(
              (res)=>{
               res
               .json()
               .then(
                 (data) =>cb(data)
              })
          .catch(err => console.error(err))
}

и

function foo(cb) {
     return fetch('foo.com')
            .then(()=>cb())
            .catch(err => console.error(err))
}

Я хочу утверждать, что обратный вызов был вызван в обоих случаях.

Я пытался

describe('ugh why can't I figure this out'?, () => {
it('is confusing', (done) => {

const testCb = jest.fn()

foo(testCb);

expect(testCb).toHaveBeenCalled()

done();

//failed: expected testCb to be called, but it was not called
}
})

Я не уверен, как двигаться вперед - я не фанат спагетти на стене, поэтому я бы лучше понял, какреализовать Jest для тестирования асинхронного кода, прежде чем я просто начать переключаться в другой синтаксис.Приведенный выше код выглядит так, как будто он должен работать, потому что обратный вызов является частью выполнения функции, поэтому, если выполняется функция более высокого порядка, обратный вызов обязательно будет выполнен и должен был быть «вызван».Очевидно, что эти рассуждения неверны, поскольку тест не проходит, но я не совсем понимаю, как это обойти.

Большое спасибо за любое направление / понимание :).

Этот шутливый пример, кажется, соответствует моему - что я пропустил?

describe('drinkAll', () => {
  test('drinks something lemon-flavored', () => {
    let drink = jest.fn();
    drinkAll(drink, 'lemon');
    expect(drink).toHaveBeenCalled();
  });

  test('does not drink something octopus-flavored', () => {
    let drink = jest.fn();
    drinkAll(drink, 'octopus');
    expect(drink).not.toHaveBeenCalled();
  });
});

1 Ответ

0 голосов
/ 21 октября 2018

Вас expect вызывают до того, как fetch вернется.Сделайте это:

foo(testCb)
  .then(_ => {
    expect(testCb).toHaveBeenCalled();
    done();
  })
  .catch(err => {
    done.fail(err);
  });

Приковав цепочку к Обещанию, возвращенному foo, мы гарантируем, что fetch вернется.После того, как вы перейдете на асинхронный режим, вы должны оставаться таким же, вы не можете смешивать синхронизирующий и асинхронный код, как вы делали это в своем опубликованном коде:

const testCb = jest.fn()

foo(testCb); // this can take an arbitrary amt of time

expect(testCb).toHaveBeenCalled() // but this happens immediately

done();

FWIW, вы также можете изменить это

return fetch('foo.com')
          .then(
              (res)=>{
               res
               .json()
               .then(
                 (data) =>cb(data)
              })

В это:

return fetch('foo.com')
          .then((res)=> res.json())
          .then(cb)
          .catch((err) => ...

Дополнительный уровень вложенных обещаний не нужен и затрудняет чтение кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...