Então, estou testando um componente que depende de um emissor de evento. Para isso, criei uma solução usando o Promises com Mocha + Chai:
it('should transition with the correct event', (done) => {
const cFSM = new CharacterFSM({}, emitter, transitions);
let timeout = null;
let resolved = false;
new Promise((resolve, reject) => {
emitter.once('action', resolve);
emitter.emit('done', {});
timeout = setTimeout(() => {
if (!resolved) {
reject('Timedout!');
}
clearTimeout(timeout);
}, 100);
}).then((state) => {
resolved = true;
assert(state.action === 'DONE', 'should change state');
done();
}).catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
});
No console, estou recebendo um 'UnhandledPromiseRejectionWarning', embora a função de rejeição esteja sendo chamada, pois mostra instantaneamente a mensagem 'AssertionError: Promise error'
(nó: 25754) UnhandledPromiseRejectionWarning: rejeição de promessa sem tratamento (ID de rejeição: 2): AssertionError: erro de promessa: esperado {objeto (mensagem, showDiff, ...)} como falso 1) deve fazer a transição com o evento correto
E então, depois de 2 segundos eu recebo
Erro: tempo limite de 2000ms excedido. Verifique se o retorno de chamada done () está sendo chamado neste teste.
O que é ainda mais estranho desde que o retorno de chamada de captura foi executado (acho que, por algum motivo, a falha de declaração impediu o restante da execução)
Agora, o mais engraçado, se eu comentar, assert.isNotOk(error...)
o teste será executado sem nenhum aviso no console. Ainda "falha" no sentido em que executa a captura.
Ainda assim, não consigo entender esses erros com promessa. Alguém pode me esclarecer?
Respostas:
O problema é causado por isso:
Se a asserção falhar, gerará um erro. Este erro fará com que
done()
nunca seja chamado, porque o código foi exibido antes dele. Isso é o que causa o tempo limite.A "rejeição de promessa não tratada" também é causada pela falha na declaração, porque se um erro for gerado em um
catch()
manipulador e não houver umcatch()
manipulador subsequente , o erro será engolido (conforme explicado neste artigo ). OUnhandledPromiseRejectionWarning
aviso está alertando você para esse fato.Em geral, se você deseja testar o código baseado em promessas no Mocha, deve confiar no fato de que o próprio Mocha já pode lidar com promessas. Você não deve usar
done()
, mas, em vez disso, retorne uma promessa do seu teste. O Mocha detectará os próprios erros.Como isso:
fonte
catch
manipulador provavelmente deve ser passado como segundo argumento parathen
. No entanto, eu não sou inteiramente certo o que a intenção do OP foi, então eu deixei como está.done.fail('msg')
neste caso.Eu recebi esse erro ao stubbing com sinon.
A correção é usar o pacote npm sinon como prometido ao resolver ou rejeitar promessas com stubs.
Ao invés de ...
Usar ...
Há também um método resolve (observe os s no final).
Consulte http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections
fonte
As bibliotecas de asserções no Mocha funcionam lançando um erro se a asserção não estiver correta. Lançar um erro resulta em uma promessa rejeitada, mesmo quando lançada na função executora fornecida ao
catch
método.No código acima, a
error
objeção é avaliada paratrue
que a biblioteca de asserções gere um erro ... que nunca seja detectado. Como resultado do erro, odone
método nunca é chamado. Odone
retorno de chamada do Mocha aceita esses erros, então você pode simplesmente encerrar todas as cadeias de promessas no Mocha com.then(done,done)
. Isso garante que o método concluído seja sempre chamado e o erro seja relatado da mesma maneira que quando o Mocha captura o erro da asserção no código síncrono.Dou crédito a este artigo pela idéia de usar .then (concluído, concluído) ao testar promessas no Mocha.
fonte
Para quem procura o erro / aviso
UnhandledPromiseRejectionWarning
fora de um ambiente de teste, pode ser porque provavelmente ninguém no código está cuidando do eventual erro em uma promessa:Por exemplo, este código mostrará o aviso relatado nesta pergunta:
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
e adicionar
.catch()
ou manipular o erro deve resolver o aviso / erroOu usando o segundo parâmetro na
then
funçãofonte
new Promise((resolve, reject) => { return reject('Error reason!'); })
funções, mas funçõesfunction test() { return new Promise((resolve, reject) => { return reject('Error reason!'); });}
internas que não precisamos usar,.catch()
mas para lidar com erros com êxito, basta usar ao chamar essa funçãotest().catch(e => console.log(e))
ou versão assíncrona /try { await test() } catch (e) { console.log(e) }
Eu enfrentei esse problema:
Foi um erro meu, eu estava substituindo um
res
objetothen(function(res)
, então mudeires
para resultar e agora está funcionando.Errado
Correção
Código de Serviço:
fonte
Aqui está a minha experiência com o E7 assíncrono / aguardar :
Caso você tenha
async helperFunction()
recebido uma chamada do seu teste ... (uma explicação com aasync
palavra-chave ES7 , quero dizer)→ certifique-se de chamar assim
await helperFunction(whateverParams)
(bem, sim, naturalmente, depois que você souber ...)E para que isso funcione (para evitar 'aguardar é uma palavra reservada'), sua função de teste deve ter um marcador assíncrono externo:
fonte
await helperFunction(...)
. Umaasync
função retorna uma promessa. Você poderia apenas lidar com a promessa retornada, como faria em uma função não marcadaasync
que retornasse uma promessa. O ponto é lidar com a promessa, ponto final. Se a função éasync
ou não, não importa.await
é apenas uma entre várias maneiras de lidar com a promessa.UnhandledPromiseRejectionWarning
para mim ... então essa resposta.Eu tive uma experiência semelhante com o Chai-Webdriver para Selenium. Eu adicionei
await
à afirmação e ela corrigiu o problema:Exemplo usando Cucumberjs:
fonte
Resolvi esse problema depois de desinstalar o webpack (problema do react js).
fonte