Я работаю над добавлением тестового покрытия к проекту 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 регистрирует сброшенную ошибку и не проходит тест, но не сбой. (т.е. контрольный наблюдатель продолжает просмотр и запуск тестов)
То, как я подошел к этому, очень сильно связано с тем, как я пишу свои функции - в принципе, любая функция, использующая обещания, должна вернуть обещание. Это позволяет использовать любые кодовые вызовы для обработки ошибок ловушек любым способом, который он считает нужным. Обратите внимание, что это мой подход, и я не собираюсь утверждать, что это единственный способ сделать что-то.
Например... Представьте, что я тестирую эту функцию:
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
в функции, чтобы поймать и бросить эту ошибку, но я не пробовал, и я не уверен, если это будет какой - нибудь более надежным.
async/await
в нашей кодовой базе, поэтому я добавил await
перед вызовом рассматриваемого метода. Это на самом деле прекрасно работает, если отклонение возвращается непосредственно из вызываемого метода. К сожалению, из-за некоторых проблем, связанных с тем, как был написан код, обещания все глубже отклоняются в стеке и не отображаются полностью вплоть до вызываемого метода, и поэтому не могут быть возвращены обратно в Jest.
Не уверен, что это помогает, но вы также можете заявить об отказе от обещаний как таковых
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');
});
});