it-roy-ru.com

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

Я работаю над добавлением тестового покрытия в проект Node, над которым я работаю, используя Jest. Код, который я тестирую, выдает ошибки в обещаниях, в результате чего на консоль записывается сообщение 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 регистрирует выданную ошибку и не проходит тест, но не вылетает. (т. е. наблюдатель продолжает наблюдать и запускать тесты)

6
Jesse Dunlap

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

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

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 для перехвата и выдачи ошибки, но я не пробовал ее и не уверен, будет ли она более надежной.

1
Kryten