próximo teste
async function check() {
throw new Error('Test');
}
expect(async () =>
await check()
).toThrow();
irá falhar e não detectará o erro corretamente (estou usando a versão mais recente do jest)
Sim, isso não é compatível atualmente. Veja https://github.com/facebook/jest/issues/1377
Ao invés de
expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."
isso funciona:
expect(check()).rejects.toEqual(new Error('Test'))
Sim, a sintaxe é estranha ...
Você também pode escrever:
let error;
try {
await check();
} catch (e) {
error = e;
}
expect(error).toEqual(new Error('Test'));
O seguinte funcionou para mim também:
async function check() {
throw new Error('Test');
}
expect(check()).rejects.toEqual(new Error('Test'))
Veja: https://facebook.github.io/jest/docs/en/tutorial-async.html#rejects
Adicionando à lista de soluções alternativas.
Se você gosta de mim, deseja detectar um tipo específico de erro e não se importa com a mensagem:
async function check() {
throw new SomeSpecificError('Whatever');
}
await check()
.then(() => {
throw new Error('Should go to .catch, not enter .then');
})
.catch((err) => {
expect(err).toBeInstanceOf(SomeSpecificError);
});
await expect(check).rejects.toThrow(SomeSpecificError);
Deve funcionar bem
await expect(check).rejects.toThrow(/DUPLICATES_DETECTED/);
é o que eu faço.
async function check() {
throw new Error("Test");
}
await expect(check).rejects.toThrow(Error);
expect(received).rejects.toThrow()
received value must be a Promise.
Received:
function: [Function check]
Você precisa invocá-lo para dar a ele a promessa real
async function check() {
throw new Error("Test");
}
await expect(check()).rejects.toThrow(Error);
Deve funcionar bem
it(`some test`, async () => {
async function check() {
try {
return Promise.reject(await asyncMethod());
} catch (error) {
throw new Error("test");
}
}
await expect(check()).rejects.toThrow(Error);
});
pode trabalhar
versão
23.4.2
23.1.2
Eu sei que é necessário uma promessa, mas o caso que você está oferecendo não é :)
Oi ! Posso estar fazendo algo errado, mas ainda tenho problemas com erros personalizados em chamadas assíncronas. Considere o seguinte:
class CustomErrorType {}
// ...
test('check throws custom error', async () => {
async function check() {
throw new CustomErrorType();
}
await expect(check()).rejects.toThrow(CustomErrorType);
});
então o teste falha com a seguinte saída:
Esperava-se que a função gerasse um erro do tipo:
"CustomErrorType"
Mas não jogou nada.
Portanto, o teste falha - embora funcione perfeitamente quando a classe lançada é Error
. Quando tento estender Error
com
`` `javascript
classe CustomErrorType estende Error {}
`` ``
então o erro é
Esperava-se que a função gerasse um erro do tipo:
"CustomErrorType"
Em vez disso, ele jogou:
Erro
Alguma pista sobre o que há de errado nessa amostra? Estou usando o jest 23.4.2.
@Marchelune Quando você escreve class CustomErrorType extends Error {}
você não definiu realmente uma nova classe. Se você der a CustomErrorType um corpo, mesmo apenas um construtor que não faz nada além de chamar super (), ele funcionará.
No caso de alguém lançar algo diferente da classe Error da instância e se esforçar para usar o conselho daquele thread (como eu fiz).
toThrow()
verificará qual valor lançado é a instância da classe Error e, se não for, o lançamento não será detectado. Isso não era óbvio pelos documentos e pelo bom senso.
Isso irá falhar, embora claramente lance:
async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`
mas isso vai funcionar (não tenho certeza se existe uma maneira melhor):
async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`
@Karabur typo toBeThruthy
deve ser toBeTruthy
Aqui está um teste explícito que garante que ele definitivamente será interrompido se NÃO for acionado e corresponder a um erro específico.
yourCoolAsyncMethod('yeah it is')
.then(ok => { // Presumes not a Promise<void>
expect(ok).toBeUndefined();
done();
})
.catch(bad => {
expect(bad).toBeDefined();
expect(bad).toMatchInlineSnapshot(
`Specifically serious error!`
);
done();
});
Olá @SimenB.
Se eu tiver isso e estiver funcionando.
async function check() {
// do something
}
await expect(check()).rejects.toThrow(InternalServerErrorException);
InternalServerErrorException é lançada com um objeto ....
Como posso também declarar propriedades no erro lançado? Por exemplo:
Aqui está um teste explícito que garante que ele definitivamente será interrompido se NÃO for acionado e corresponder a um erro específico.
yourCoolAsyncMethod('yeah it is') .then(ok => { expect(ok).toBeUndefined(); done(); }) .catch(bad => { expect(bad).toBeDefined(); expect(bad).toMatchInlineSnapshot( `Specifically serious error!` ); done(); });
O problema disso é que seu teste será aprovado se o código nunca tiver erros.
Portanto, esse teste realmente não ofereceria muito valor, pois os resultados esperados variam com base em se o código que está testando tem um erro ou não.
Os testes devem ter um fluxo negativo ou positivo e devemos testar apenas o que é necessário para testar. Esse tipo de aleatoriedade não é o maior.
Olá, @ David-Tennant 🖐
Obrigado por apontar isso. Eu estava trabalhando em um método Promise<notVoid>
naquela época. Percebi que não compartilho uma solução comum que também seja válida para Promise<void>
. Atualizei minha resposta com um comentário que diz que fiz suposições. Eu concordo com você sobre o fluxo.
Obrigado 💨
Olá @futuredayv 👋
Olá, @ David-Tennant 🖐
Obrigado por apontar isso. Eu estava trabalhando em um método
Promise<notVoid>
naquela época. Percebi que não compartilho uma solução comum que também seja válida paraPromise<void>
. Atualizei minha resposta com um comentário que diz que fiz suposições. Eu concordo com você sobre o fluxo.Obrigado 💨
O problema é que seu teste ainda passará se o teste retornar inválido. Qual deve ser um bug, certo?
Chamar done()
significa "Meu teste foi aprovado da maneira esperada e estou pronto para passar para o próximo teste"
yourCoolAsyncMethod('yeah it is')
// -- Lets say your method does not throw, and returns void instead
.then(ok => { // Presumes not a Promise<void>
expect(ok).toBeUndefined(); // -- At this point if it was void, this would pass
done(); // -- Then your test would end and the catch would not be reached
// -- Now you have unknown behavior passing a test where it's suppose to catch a fail
})
.catch(bad => {
// -- This block does not run because done() is called above
expect(bad).toBeDefined();
expect(bad).toMatchInlineSnapshot(
`Specifically serious error!`
);
done();
});
Não tenho certeza de qual seria a solução para o seu caso de uso. Mas eu começaria não chamando done()
no then
ou talvez lançando um erro no "então" para ter certeza de que o teste falhou,
yourCoolAsyncMethod('yeah it is')
.then(ok => throw new Error("This block of code should not be reached")
.catch(bad => {
expect(bad).toBeDefined();
expect(bad).toMatchInlineSnapshot(
`Specifically serious error!`
);
done();
});
No caso de alguém lançar algo diferente da classe Error da instância e se esforçar para usar o conselho daquele thread (como eu fiz).
toThrow()
verificará qual valor lançado é a instância da classe Error e, se não for, o lançamento não será detectado. Isso não era óbvio pelos documentos e pelo bom senso.
Isso irá falhar, embora claramente lance:async function f() {throw 'aa'} const res = await expect(f()).rejects.toThrow()`
mas isso vai funcionar (não tenho certeza se existe uma maneira melhor):
async function f() {throw 'aa'} const res = await expect(f()).rejects.toBeTruthy()`
Uma maneira ligeiramente melhor é usar toBeDefined()
vez de toBeTruthy()
:
async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`
Comentários muito úteis
Ao invés de
isso funciona:
Sim, a sintaxe é estranha ...