Testando Código Assíncrono
Esta página foi traduzida por PageTurner AI (beta). Não é oficialmente endossada pelo projeto. Encontrou um erro? Reportar problema →
É comum em JavaScript que o código execute de forma assíncrona. Quando você tem código que roda assincronamente, o Jest precisa saber quando o código sendo testado foi concluído antes de passar para outro teste. O Jest oferece várias maneiras de lidar com isso.
Promessas
Retorne uma promessa do seu teste, e o Jest aguardará até que ela seja resolvida. Se a promessa for rejeitada, o teste falhará.
Por exemplo, imagine que fetchData retorna uma promessa que deve resolver para a string 'peanut butter'. Poderíamos testá-la com:
test('the data is peanut butter', () => {
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});
Async/Await
Alternativamente, você pode usar async e await em seus testes. Para escrever um teste assíncrono, use a palavra-chave async antes da função passada para test. Por exemplo, o mesmo cenário com fetchData pode ser testado com:
test('the data is peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});
test('the fetch fails with an error', async () => {
expect.assertions(1);
try {
await fetchData();
} catch (error) {
expect(error).toMatch('error');
}
});
Você pode combinar async e await com .resolves ou .rejects.
test('the data is peanut butter', async () => {
await expect(fetchData()).resolves.toBe('peanut butter');
});
test('the fetch fails with an error', async () => {
await expect(fetchData()).rejects.toMatch('error');
});
Nesses casos, async e await são essencialmente açúcar sintático para a mesma lógica usada nos exemplos com promessas.
Certifique-se de retornar (ou usar await) a promessa - se você omitir a declaração return/await, seu teste será concluído antes que a promessa retornada por fetchData seja resolvida ou rejeitada.
Se você espera que uma promessa seja rejeitada, use o método .catch. Lembre-se de adicionar expect.assertions para verificar se um número específico de asserções é chamado. Caso contrário, uma promessa cumprida não falharia o teste.
test('the fetch fails with an error', () => {
expect.assertions(1);
return fetchData().catch(error => expect(error).toMatch('error'));
});
Callbacks
Se você não usa promessas, pode utilizar callbacks. Por exemplo, suponha que fetchData, em vez de retornar uma promessa, espera um callback, ou seja, busca alguns dados e chama callback(null, data) quando completa. Você quer testar se esses dados retornados são a string 'peanut butter'.
Por padrão, os testes do Jest são concluídos quando atingem o fim de sua execução. Isso significa que este teste não funcionará como pretendido:
// Don't do this!
test('the data is peanut butter', () => {
function callback(error, data) {
if (error) {
throw error;
}
expect(data).toBe('peanut butter');
}
fetchData(callback);
});
O problema é que o teste será concluído assim que fetchData terminar, antes mesmo de chamar o callback.
Existe uma forma alternativa de test que corrige isso. Em vez de colocar o teste em uma função sem argumentos, use um único argumento chamado done. O Jest aguardará até que o callback done seja chamado para finalizar o teste.
test('the data is peanut butter', done => {
function callback(error, data) {
if (error) {
done(error);
return;
}
try {
expect(data).toBe('peanut butter');
done();
} catch (error) {
done(error);
}
}
fetchData(callback);
});
Se done() nunca for chamado, o teste falhará (com erro de timeout), que é o comportamento desejado.
Se a asserção expect falhar, ela lançará um erro e done() não será chamado. Se quisermos ver no log do teste o motivo da falha, devemos envolver expect em um bloco try e passar o erro no bloco catch para done. Caso contrário, teremos um erro de timeout opaco que não mostra qual valor foi recebido por expect(data).
O Jest lançará um erro se a mesma função de teste receber um callback done() e retornar uma promessa. Isso é feito como precaução para evitar vazamentos de memória em seus testes.
.resolves / .rejects
Você também pode usar o matcher .resolves em sua asserção expect, e o Jest aguardará até que essa promessa seja resolvida. Se a promessa for rejeitada, o teste falhará automaticamente.
test('the data is peanut butter', () => {
return expect(fetchData()).resolves.toBe('peanut butter');
});
Certifique-se de retornar a asserção - se você omitir esta declaração return, seu teste será concluído antes que a promessa retornada por fetchData seja resolvida e então() tenha chance de executar o callback.
Se você espera que uma promessa seja rejeitada, use o matcher .rejects. Ele funciona de forma análoga ao matcher .resolves. Se a promessa for cumprida, o teste falhará automaticamente.
test('the fetch fails with an error', () => {
return expect(fetchData()).rejects.toMatch('error');
});
Nenhuma dessas formas é particularmente superior às outras, e você pode combiná-las em uma base de código ou até mesmo em um único arquivo. Tudo depende de qual estilo você considera que torna seus testes mais simples.