codecamp

Jest 设置和拆卸

写测试的时候你经常需要在运行测试前做一些准备工作,和在运行测试后进行一些整理工作。 Jest 提供辅助函数来处理这个问题。

为多次测试重复设置

如果你有一些要为多次测试重复设置的工作,你可以使用 ​beforeEach ​和 ​afterEach​。

例如,我们考虑一些与城市信息数据库进行交互的测试。 你必须在每个测试之前调用方法 ​initializeCityDatabase() ​,同时必须在每个测试后,调用方法 ​clearCityDatabase()​。 你可以这样做:

  1. beforeEach(() => {
  2. initializeCityDatabase();
  3. });
  4. afterEach(() => {
  5. clearCityDatabase();
  6. });
  7. test('city database has Vienna', () => {
  8. expect(isCity('Vienna')).toBeTruthy();
  9. });
  10. test('city database has San Juan', () => {
  11. expect(isCity('San Juan')).toBeTruthy();
  12. });

beforeEach ​和 ​afterEach ​能够通过与 异步代码测试 相同的方式处理异步代码 — — 他们可以采取 ​done ​参数或返回一个 promise。 例如,如果 ​initializeCityDatabase() ​返回解决数据库初始化时的 promise ,我们会想返回这一 promise︰

  1. beforeEach(() => {
  2. return initializeCityDatabase();
  3. });

一次性设置

在某些情况下,你只需要在文件的开头做一次设置。当设置是异步的时,这可能会特别麻烦,因此你就不能内联执行。Jest 提供 ​beforeAll ​和 ​afterAll ​处理这种情况。

例如,如果 ​initializeCityDatabase ​和 ​clearCityDatabase ​都返回了 promise ,城市数据库可以在测试中重用,我们就能把我们的测试代码改成这样:

  1. beforeAll(() => {
  2. return initializeCityDatabase();
  3. });
  4. afterAll(() => {
  5. return clearCityDatabase();
  6. });
  7. test('city database has Vienna', () => {
  8. expect(isCity('Vienna')).toBeTruthy();
  9. });
  10. test('city database has San Juan', () => {
  11. expect(isCity('San Juan')).toBeTruthy();
  12. });

作用域

默认情况下,​before ​和 ​after ​的块可以应用到文件中的每个测试。 此外可以通过 ​describe ​块来将测试分组。 当 ​before ​和 ​after ​的块在 ​describe ​块内部时,则其只适用于该 ​describe ​块内的测试。

例如,我们不仅有一个城市数据库,而且还有一个食品数据库。 我们可以为不同的测试进行不同的设置:

  1. // Applies to all tests in this file
  2. beforeEach(() => {
  3. return initializeCityDatabase();
  4. });
  5. test('city database has Vienna', () => {
  6. expect(isCity('Vienna')).toBeTruthy();
  7. });
  8. test('city database has San Juan', () => {
  9. expect(isCity('San Juan')).toBeTruthy();
  10. });
  11. describe('matching cities to foods', () => {
  12. // Applies only to tests in this describe block
  13. beforeEach(() => {
  14. return initializeFoodDatabase();
  15. });
  16. test('Vienna <3 sausage', () => {
  17. expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
  18. });
  19. test('San Juan <3 plantains', () => {
  20. expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
  21. });
  22. });

注意,顶级的 ​beforeEach ​在 ​describe ​块级的 ​beforeEach ​之前被执行。 这可能有助于说明所有钩子的执行顺序。

  1. beforeAll(() => console.log('1 - beforeAll'));
  2. afterAll(() => console.log('1 - afterAll'));
  3. beforeEach(() => console.log('1 - beforeEach'));
  4. afterEach(() => console.log('1 - afterEach'));
  5. test('', () => console.log('1 - test'));
  6. describe('Scoped / Nested block', () => {
  7. beforeAll(() => console.log('2 - beforeAll'));
  8. afterAll(() => console.log('2 - afterAll'));
  9. beforeEach(() => console.log('2 - beforeEach'));
  10. afterEach(() => console.log('2 - afterEach'));
  11. test('', () => console.log('2 - test'));
  12. });
  13. // 1 - beforeAll
  14. // 1 - beforeEach
  15. // 1 - test
  16. // 1 - afterEach
  17. // 2 - beforeAll
  18. // 1 - beforeEach
  19. // 2 - beforeEach
  20. // 2 - test
  21. // 2 - afterEach
  22. // 1 - afterEach
  23. // 2 - afterAll
  24. // 1 - afterAll

describe 和 test 块的执行顺序

Jest 会在所有真正的测试开始之前执行测试文件里所有的 describe 处理程序(handlers)。 这是在 ​before* ​和 ​after* ​处理程序里面 (而不是在 describe 块中)进行准备工作和整理工作的另一个原因。 默认情况下,当 describe 块运行完后,Jest 会按照 test 出现的顺序(译者注:原文是in the order they were encountered in the collection phase)依次运行所有测试,,等待每一个测试完成并整理好,然后才继续往下走。

考虑以下示例测试文件和输出:

  1. describe('outer', () => {
  2. console.log('describe outer-a');
  3. describe('describe inner 1', () => {
  4. console.log('describe inner 1');
  5. test('test 1', () => {
  6. console.log('test for describe inner 1');
  7. expect(true).toEqual(true);
  8. });
  9. });
  10. console.log('describe outer-b');
  11. test('test 1', () => {
  12. console.log('test for describe outer');
  13. expect(true).toEqual(true);
  14. });
  15. describe('describe inner 2', () => {
  16. console.log('describe inner 2');
  17. test('test for describe inner 2', () => {
  18. console.log('test for describe inner 2');
  19. expect(false).toEqual(false);
  20. });
  21. });
  22. console.log('describe outer-c');
  23. });
  24. // describe outer-a
  25. // describe inner 1
  26. // describe outer-b
  27. // describe inner 2
  28. // describe outer-c
  29. // test for describe inner 1
  30. // test for describe outer
  31. // test for describe inner 2

通用建议

如果测试失败,第一件要检查的事就是,当仅运行这条测试时,它是否仍然失败。 要使用Jest仅运行一个​test​,请将该测试命令临时更改为​test.only​:

  1. test.only('this will be the only test that runs', () => {
  2. expect(true).toBe(false);
  3. });
  4. test('this test will not run', () => {
  5. expect('A').toBe('A');
  6. });

如果你有一个测试,当它作为一个更大的用例中的一部分时,经常运行失败,但是当你单独运行它时,并不会失败,所以最好考虑其他测试对这个测试的影响。 通常可以通过修改 ​beforeEach ​来清除一些共享的状态来修复这种问题。 如果不确定是否正在修改某些共享状态,也可以尝试使用​beforeEach​记录数据。


Jest 测试异步代码
Jest 模拟函数
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }