Setup and Teardown
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.
Repetindo a Configuração Para Vários Testes
Se você tem algum trabalho que você precisa fazer repetidamente por muitos testes, você pode usar beforeEach
e afterEach
.
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 configurar uma vez, no início de um arquivo. This can be especially bothersome when the setup is asynchronous, so you can't do it inline. Jest fornece beforeAll
e afterAll
para lidar com essa situação.
Por exemplo, se ambos initializeCityDatabase
e clearCityDatabase
retornaram promessas, e o banco de dados de cidades poderia ser reutilizado entre os testes, nós podemos alterar 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
Por padrão, os blocos before
e after
se aplicam a todos os testes em um arquivo. Você também pode agrupar testes junto usando um bloco de describe
. Quando eles estão dentro de um bloco de describe
, os blocos before
e after
só se aplicam aos testes dentro desse bloco de describe
.
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 sausage', () => {
expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
});
test('San Juan <3 plantains', () => {
expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
});
});
Note that the top-level beforeEach
is executed before the beforeEach
inside the describe
block. It may help to illustrate the order of execution of all 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 dos blocos describe e test
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('outer', () => {
console.log('describe outer-a');
describe('describe inner 1', () => {
console.log('describe inner 1');
test('test 1', () => {
console.log('test for describe inner 1');
expect(true).toEqual(true);
});
});
console.log('describe outer-b');
test('test 1', () => {
console.log('test for describe outer');
expect(true).toEqual(true);
});
describe('describe inner 2', () => {
console.log('describe inner 2');
test('test for describe inner 2', () => {
console.log('test for describe inner 2');
expect(false).toEqual(false);
});
});
console.log('describe outer-c');
});
// describe outer-a
// describe inner 1
// describe outer-b
// describe inner 2
// describe outer-c
// test for describe inner 1
// test for describe outer
// test for describe inner 2
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. To run only one test with Jest, temporarily change that test
command to a 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
. If you're not sure whether some shared state is being modified, you can also try a beforeEach
that logs data.