通常在编写测试时,您有一些设置工作需要在测试运行前完成,还有一些完成工作需要在测试运行后完成。Jest提供了帮助函数来处理这个问题。
为许多测试重复设置
如果很多测试有需要重复去做的工作,你可以使用 beforeEach
和 afterEach
。
例如,假设有几个测试与 city 数据库交互。你有一个 initializeCityDatabase()
方法必须在每次测试之前调用,以及一个方法 clearCityDatabase()
必须在每次结束之后调用。你可以如下这样做:
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
和 afterEach
可以处理异步代码,方式和测试异步代码是一样的,他们可以接收一个done
参数或返回一个 promise。例如,如果 initializeCityDatabase()
当 city 数据库初始化完成后返回一个 resolved 状态的 promise,我们希望返回这个 promise:
beforeEach(() => {
return initializeCityDatabase();
});
一次性设置
有时候,你仅仅需要在文件的开头安装一次。挡在设置异步的时候,这个尤其麻烦,所以你不能内联地完成它。Jest 提供了 beforeAll
和 afterAll
来处理这种情况。
例如,如果 initializeCityDatabase
和 clearCityDatabase
返回 promises,并且这个 city 数据库可以在测试之间被复用,那么我们的测试代码可以修改成这样:
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();
});
范围
默认情况下,before
和 after
块应用到文件中的每个测试。你可以使用 describe
块将测试组织到一起。当他们都在一个 describe
块里,这个 before
和 after
块仅仅作用于 describe
块内的测试。
例如,假设我们不仅有一个 city 数据库,而且还有一个 food 数据库。我们可以为不同测试做不同的安装:
// 应用到文件中的所有测试
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', () => {
// 仅仅应用到 describe 块中的测试
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);
});
});
注意,最外层的 beforeEach
是先于 describe
块里的 beforeEach
执行的。它可能有助于说明所有钩子的执行顺序。
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
// 记住 before 和 after 作用于每个测试(上面有两个 test),然后就是如上面所说,外层的 beforeEach 在内层的 beforeEach 之前执行
describe 块和 test 块执行顺序
在一个测试文件中,在执行任何真正的测试之前,Jest 先执行所有 describe 处理程序。这也就是我们在 describe 块中把安装和拆卸写在 before*
和 after*
处理程序的原因。一旦 describe 块完成,默认情况下Jest将按照在收集阶段遇到的顺序连续运行所有测试,等待每个测试完成并被整理,然后再继续。
考虑以下演示性测试文件和输出:
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
通用建议
如果一个测试失败,第一件应该做的事情就是,测试作为 唯一测试运行的时候,是否失败。在 jest 中运行仅仅单个测试(only one test)是简单的 - 仅仅需要临时将 test
改完 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');
});
如果您有一个测试在作为较大的套件的一部分运行时经常失败,但在单独运行时不会失败,那么很有可能来自其他测试的内容会干扰这个测试。通常可以通过清除 beforeEach
之前的一些共享状态来解决这个问题。如果不确定是否某些共享状态被修改了,还可以尝试 beforeEach
记录数据。
网友评论