Skip to main content
Versão: Próximo

Configuração e Desmontagem

Muitas vezes ao escrever testes você tem algum trabalho de configuração que precisa acontecer antes de executar testes, e você tem algum trabalho de acabamento que precisa acontecer após os testes executarem. Jest fornece funções de auxilio para lidar com isso.

Repeating Setup

Se você tem algo que precisa ser executado repetidamente antes ou depois para muitos testes, você pode usar os hooks beforeEach e afterEach para isso.

Por exemplo, digamos que vários testes interagem com um banco de dados de cidades. Você tem um método initializeCityDatabase() que deve ser chamado antes de cada um destes testes e um método clearCityDatabase() que deve ser chamado depois de cada um destes testes. Você pode fazer 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();
});

beforeEach e afterEach podem lidar com código assíncrono da mesma forma que testes podem lidar com código assíncrono - podem tanto levar um parâmetro done ou retornar uma promessa. Por exemplo, se initializeCityDatabase() tiver retornado uma promessa que resolve quando o banco de dados foi inicializado, gostaríamos de retornar essa promessa:

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

Configuração Única

Em alguns casos, você só precisa executar ou configurar algo uma vez, no início de um arquivo. Isto pode ser especialmente incômodo quando a instalação é assíncrona, portanto, não pode fazer isso "inline". Jest fornece os hooks beforeAll e afterAll para lidar com essa situação.

For example, if both initializeCityDatabase() and clearCityDatabase() returned promises, and the city database could be reused between tests, we could change our test code to:

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

The top level before* and after* hooks apply to every test in a file. The hooks declared inside a describe block apply only to the tests within that describe block.

Por exemplo, digamos que nós não temos apenas um banco de dados de cidades, mas também um banco de dados de alimentos. Nós podemos fazer uma configuração diferente 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);
});
});

Observe que o beforeeach de nível superior é executado antes do beforeEach dentro do bloco describe. Isso pode ajudar 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

Order of Execution

Jest executes all describe handlers in a test file before it executes any of the actual tests. This is another reason to do setup and teardown inside before* and after* handlers rather than inside the describe blocks. Once the describe blocks are complete, by default Jest runs all the tests serially in the order they were encountered in the collection phase, waiting for each to finish and be tidied up before moving on.

Considere o seguinte arquivo de teste ilustrativo e a 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

Just like the describe and test blocks Jest calls the before* and after* hooks in the order of declaration. Note that the after* hooks of the enclosing scope are called first. For example, here is how you can set up and tear down resources which depend on each other:

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
note

If you are using jasmine2 test runner, take into account that it calls the after* hooks in the reverse order of declaration. To have identical output, the above example should be altered like this:

  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'));

// ...

Conselho geral

Se um teste está falhando, uma das primeiras coisas a verificar deveria ser se o teste está falhando quando é o único teste que é executado. Para executar apenas um único 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ê tiver uma teste que muitas vezes falha quando ele é executado como parte de um conjunto maior, mas não falha quando você executá-lo sozinho, é uma boa aposta que algo de um teste diferente está interferindo com ele. Muitas vezes, você pode consertar isso, limpando algum estado compartilhado com beforeEach. Se você não tem certeza se algum estado compartilhado está sendo modificado, você também pode tentar um beforeEach para emitir um log dos dados.