寫(xiě)測(cè)試的時(shí)候你經(jīng)常需要在運(yùn)行測(cè)試前做一些準(zhǔn)備工作,和在運(yùn)行測(cè)試后進(jìn)行一些整理工作。 Jest 提供輔助函數(shù)來(lái)處理這個(gè)問(wèn)題。
如果你有一些要為多次測(cè)試重復(fù)設(shè)置的工作,你可以使用 ?beforeEach
?和 ?afterEach
?。
例如,我們考慮一些與城市信息數(shù)據(jù)庫(kù)進(jìn)行交互的測(cè)試。 你必須在每個(gè)測(cè)試之前調(diào)用方法 ?initializeCityDatabase()
?,同時(shí)必須在每個(gè)測(cè)試后,調(diào)用方法 ?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
?能夠通過(guò)與 異步代碼測(cè)試 相同的方式處理異步代碼 — — 他們可以采取 ?done
?參數(shù)或返回一個(gè) promise。 例如,如果 ?initializeCityDatabase()
?返回解決數(shù)據(jù)庫(kù)初始化時(shí)的 promise ,我們會(huì)想返回這一 promise︰
beforeEach(() => {
return initializeCityDatabase();
});
在某些情況下,你只需要在文件的開(kāi)頭做一次設(shè)置。當(dāng)設(shè)置是異步的時(shí),這可能會(huì)特別麻煩,因此你就不能內(nèi)聯(lián)執(zhí)行。Jest 提供 ?beforeAll
?和 ?afterAll
?處理這種情況。
例如,如果 ?initializeCityDatabase
?和 ?clearCityDatabase
?都返回了 promise ,城市數(shù)據(jù)庫(kù)可以在測(cè)試中重用,我們就能把我們的測(cè)試代碼改成這樣:
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();
});
默認(rèn)情況下,?before
?和 ?after
?的塊可以應(yīng)用到文件中的每個(gè)測(cè)試。 此外可以通過(guò) ?describe
?塊來(lái)將測(cè)試分組。 當(dāng) ?before
?和 ?after
?的塊在 ?describe
?塊內(nèi)部時(shí),則其只適用于該 ?describe
?塊內(nèi)的測(cè)試。
例如,我們不僅有一個(gè)城市數(shù)據(jù)庫(kù),而且還有一個(gè)食品數(shù)據(jù)庫(kù)。 我們可以為不同的測(cè)試進(jìn)行不同的設(shè)置:
// 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);
});
});
注意,頂級(jí)的 ?beforeEach
?在 ?describe
?塊級(jí)的 ?beforeEach
?之前被執(zhí)行。 這可能有助于說(shuō)明所有鉤子的執(zhí)行順序。
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
Jest 會(huì)在所有真正的測(cè)試開(kāi)始之前執(zhí)行測(cè)試文件里所有的 describe 處理程序(handlers)。 這是在 ?before*
?和 ?after*
?處理程序里面 (而不是在 describe 塊中)進(jìn)行準(zhǔn)備工作和整理工作的另一個(gè)原因。 默認(rèn)情況下,當(dāng) describe 塊運(yùn)行完后,Jest 會(huì)按照 test 出現(xiàn)的順序(譯者注:原文是in the order they were encountered in the collection phase)依次運(yùn)行所有測(cè)試,,等待每一個(gè)測(cè)試完成并整理好,然后才繼續(xù)往下走。
考慮以下示例測(cè)試文件和輸出:
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
如果測(cè)試失敗,第一件要檢查的事就是,當(dāng)僅運(yùn)行這條測(cè)試時(shí),它是否仍然失敗。 要使用Jest僅運(yùn)行一個(gè)?test
?,請(qǐng)將該測(cè)試命令臨時(shí)更改為?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');
});
如果你有一個(gè)測(cè)試,當(dāng)它作為一個(gè)更大的用例中的一部分時(shí),經(jīng)常運(yùn)行失敗,但是當(dāng)你單獨(dú)運(yùn)行它時(shí),并不會(huì)失敗,所以最好考慮其他測(cè)試對(duì)這個(gè)測(cè)試的影響。 通常可以通過(guò)修改 ?beforeEach
?來(lái)清除一些共享的狀態(tài)來(lái)修復(fù)這種問(wèn)題。 如果不確定是否正在修改某些共享狀態(tài),也可以嘗試使用?beforeEach
?記錄數(shù)據(jù)。
更多建議: