Ir para o conteúdo principal
Versão: 29.7

Configuração e Finalização

Tradução Beta Não Oficial

Esta página foi traduzida por PageTurner AI (beta). Não é oficialmente endossada pelo projeto. Encontrou um erro? Reportar problema →

Ao escrever testes, frequentemente você precisa realizar alguns preparativos antes da execução dos testes e algumas finalizações após sua conclusão. O Jest oferece funções auxiliares para lidar com esses cenários.

Configuração Repetitiva

Se você precisa executar determinadas ações repetidamente em múltiplos testes, pode usar os hooks beforeEach e afterEach.

Por exemplo, suponha que vários testes interajam com um banco de dados de cidades. Você possui um método initializeCityDatabase() que deve ser chamado antes de cada teste e um método clearCityDatabase() que deve ser chamado após cada teste. Você pode implementar isso com:

beforeEach(() => {
initializeCityDatabase();
});

afterEach(() => {
clearCityDatabase();
});

test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});

Os hooks beforeEach e afterEach lidam com código assíncrono da mesma forma que os testes lidam com código assíncrono - eles podem receber um parâmetro done ou retornar uma promise. Por exemplo, se initializeCityDatabase() retornasse uma promise resolvida quando o banco estivesse inicializado, deveríamos retornar essa promise:

beforeEach(() => {
return initializeCityDatabase();
});

Configuração Única

Em alguns casos, você só precisa executar a configuração uma vez, no início do arquivo. Isso é especialmente complicado quando a configuração é assíncrona, pois não pode ser feita inline. O Jest fornece os hooks beforeAll e afterAll para essas situações.

Por exemplo, se tanto initializeCityDatabase() quanto clearCityDatabase() retornassem promises, e o banco de dados de cidades pudesse ser reutilizado entre testes, poderíamos ajustar nosso código de teste para:

beforeAll(() => {
return initializeCityDatabase();
});

afterAll(() => {
return clearCityDatabase();
});

test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});

Escopo

Os hooks before* e after* de nível superior aplicam-se a todos os testes de um arquivo. Os hooks declarados dentro de um bloco describe aplicam-se apenas aos testes dentro desse bloco describe.

Por exemplo, suponha que além do banco de cidades, tivéssemos um banco de alimentos. Poderíamos fazer configurações diferentes para diferentes testes:

// Applies to all tests in this file
beforeEach(() => {
return initializeCityDatabase();
});

test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});

describe('matching cities to foods', () => {
// Applies only to tests in this describe block
beforeEach(() => {
return initializeFoodDatabase();
});

test('Vienna <3 veal', () => {
expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
});

test('San Juan <3 plantains', () => {
expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
});
});

Note que o beforeEach de nível superior é executado antes do beforeEach dentro do bloco describe. Isso ajuda a ilustrar a ordem de execução de todos os hooks.

beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));

test('', () => console.log('1 - test'));

describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'));
afterAll(() => console.log('2 - afterAll'));
beforeEach(() => console.log('2 - beforeEach'));
afterEach(() => console.log('2 - afterEach'));

test('', () => console.log('2 - test'));
});

// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll

Ordem de Execução

O Jest executa todos os handlers describe em um arquivo de teste antes de executar qualquer teste real. Essa é outra razão para fazer configurações e finalizações dentro de handlers before* e after*, em vez de dentro dos blocos describe. Após a conclusão dos blocos describe, por padrão o Jest executa todos os testes em série na ordem em que foram coletados, aguardando a conclusão e limpeza de cada um antes de prosseguir.

Considere o seguinte arquivo de teste ilustrativo e sua saída:

describe('describe outer', () => {
console.log('describe outer-a');

describe('describe inner 1', () => {
console.log('describe inner 1');

test('test 1', () => console.log('test 1'));
});

console.log('describe outer-b');

test('test 2', () => console.log('test 2'));

describe('describe inner 2', () => {
console.log('describe inner 2');

test('test 3', () => console.log('test 3'));
});

console.log('describe outer-c');
});

// describe outer-a
// describe inner 1
// describe outer-b
// describe inner 2
// describe outer-c
// test 1
// test 2
// test 3

Assim como os blocos describe e test, o Jest chama os hooks before* e after* na ordem de declaração. Observe que os hooks after* do escopo superior são chamados primeiro. Por exemplo, veja como configurar e finalizar recursos interdependentes:

beforeEach(() => console.log('connection setup'));
beforeEach(() => console.log('database setup'));

afterEach(() => console.log('database teardown'));
afterEach(() => console.log('connection teardown'));

test('test 1', () => console.log('test 1'));

describe('extra', () => {
beforeEach(() => console.log('extra database setup'));
afterEach(() => console.log('extra database teardown'));

test('test 2', () => console.log('test 2'));
});

// connection setup
// database setup
// test 1
// database teardown
// connection teardown

// connection setup
// database setup
// extra database setup
// test 2
// extra database teardown
// database teardown
// connection teardown
"message": "nota"

Se você estiver usando o executor de testes jasmine2, considere que ele chama os hooks after* na ordem inversa à declaração. Para obter saída idêntica, o exemplo acima deve ser ajustado assim:

  beforeEach(() => console.log('connection setup'));
+ afterEach(() => console.log('connection teardown'));

beforeEach(() => console.log('database setup'));
+ afterEach(() => console.log('database teardown'));

- afterEach(() => console.log('database teardown'));
- afterEach(() => console.log('connection teardown'));

// ...

Recomendações Gerais

Se um teste está falhando, uma das primeiras verificações deve ser se ele falha quando executado isoladamente. Para executar apenas um teste com Jest, altere temporariamente o comando test para test.only:

test.only('this will be the only test that runs', () => {
expect(true).toBe(false);
});

test('this test will not run', () => {
expect('A').toBe('A');
});

Se você tem um teste que frequentemente falha quando executado como parte de um conjunto maior, mas não falha quando executado isoladamente, é bem provável que algo de outro teste esteja interferindo com este. Geralmente, você pode corrigir isso limpando algum estado compartilhado com beforeEach. Se não tiver certeza se algum estado compartilhado está sendo modificado, também pode tentar usar um beforeEach que registre os dados em log.