Как мне не пройти тест в Jest, когда происходит непринятое отклонение обещания?

1

Я работаю над добавлением тестового покрытия к проекту Node, над которым я работаю над использованием Jest. Код, который я тестирую, бросает ошибки в рамках обещаний, в результате чего на UnhandledPromiseRejectionWarning регистрируется сообщение UnhandledPromiseRejectionWarning.

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

Я нашел в документации Node, что вы можете поймать эти предупреждения и обработать их...

process.on('unhandledRejection', (error) => {
  throw error; // Or whatever you like...
});

Поэтому кажется, что было бы довольно просто добавить этот код в мои тестовые примеры. В конце концов, Error вызванная тестом, должна привести к сбою теста...

describe('...', () => {
  it('...', () => {
    process.on('uncaughtRejection', (error) => {
      throw error;
    });

    // the rest of my test goes here
  });
});

К сожалению, поведение, которое я вижу, заключается в том, что ошибка возникает, но Jest не понимает и не проходит тест. Вместо этого Jest вылетает с этой ошибкой, и тесты не продолжают работать. Это не очень желательно и кажется неправильным поведением.

Выбрасывание ошибки вне обработчика uncaughtRejection работает так, как ожидалось: Jest регистрирует сброшенную ошибку и не проходит тест, но не сбой. (т.е. контрольный наблюдатель продолжает просмотр и запуск тестов)

  • 0
    Вы смотрели в документах, чтобы ожидать. ToThrow ()? facebook.github.io/jest/docs/en/expect.html#tothrowerror
  • 0
    У меня есть. Я на самом деле поигрался с упаковкой моего вызова в wait.not.toThrow () или альтернативной опции, которая ожидала, что возвращенное обещание разрешится. Это работало довольно хорошо для любых исключений / отклонений, которые произошли непосредственно в вызываемом методе. Я прокомментировал ниже, заявив, что на самом деле проблема заключается в более глубоких отклонениях обещаний в коде, которые не передаются должным образом. К сожалению, я не знаю, есть ли простое решение этой проблемы, кроме простого рефакторинга кода по ходу дела.
Показать ещё 1 комментарий
Теги:
unit-testing
jest

2 ответа

1

То, как я подошел к этому, очень сильно связано с тем, как я пишу свои функции - в принципе, любая функция, использующая обещания, должна вернуть обещание. Это позволяет использовать любые кодовые вызовы для обработки ошибок ловушек любым способом, который он считает нужным. Обратите внимание, что это мой подход, и я не собираюсь утверждать, что это единственный способ сделать что-то.

Например... Представьте, что я тестирую эту функцию:

const myFunction = () => {
    return doSomethingWithAPromise()
        .then(() => {
            console.log('no problems!');
            return true;
        });
};

Тест будет выглядеть примерно так:

describe('...', () => {
    it('...', () => {
        return myFunction()
            .then((value) => {
                expect(value).toBe(true);
            });
    });
});

Это отлично работает. Теперь, что произойдет, если обещание будет отвергнуто? В моем тесте отклоненное обещание передается обратно в Jest (потому что я возвращаю результат моего вызова функции), и Jest может сообщить об этом.

Если вместо этого ваша функция не вернет обещание, вам может понадобиться сделать что-то вроде этого:

const myOtherFunction = () => {
    doSomethingWithAPromise()
        .then(() => {
            console.log('no problems!');
            return true;
        })
        .catch((err) => {
             // throw the caught error here
             throw err;
        });
};

В отличие от вышеприведенного примера, для Jest не существует (прямого) способа обработки отклоненного обещания, потому что вы не передаете обещание обратно в Jest. Один из способов избежать этого может быть, чтобы обеспечить есть catch в функции, чтобы поймать и бросить эту ошибку, но я не пробовал, и я не уверен, если это будет какой - нибудь более надежным.

  • 0
    Спасибо за ваше предложение. Я на самом деле пробовал что-то подобное. Мы используем async/await в нашей кодовой базе, поэтому я добавил await перед вызовом рассматриваемого метода. Это на самом деле прекрасно работает, если отклонение возвращается непосредственно из вызываемого метода. К сожалению, из-за некоторых проблем, связанных с тем, как был написан код, обещания все глубже отклоняются в стеке и не отображаются полностью вплоть до вызываемого метода, и поэтому не могут быть возвращены обратно в Jest.
  • 0
    Хм ... хорошо, если ошибки "проглатываются" где-то глубоко в коде, кажется, что вы никогда не сможете их перехватить: - /
0

Не уверен, что это помогает, но вы также можете заявить об отказе от обещаний как таковых

index.js

module.exports = () => {
  return Promise.reject('it didnt work');
}

index.spec.js

const thing = require('../src/index');

describe('rejected promise', () => {
  it('should reject with a reason', ()=> {

    return expect(thing()).rejects.toEqual('it didnt work');
   });
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню