前端測試框架Jest系列教程 -- Asynchronous(測試異步代碼)

寫在前面:

  在JavaScript代碼中,異步運行是很常見的。當你有異步運行的代碼時,Jest須要知道它測試的代碼什麼時候完成,而後才能繼續進行另外一個測試。Jest提供了幾種方法來處理這個問題。html

測試異步代碼的三種實現方式:

方法一:回調函數前端

這是很是常見的通用處理方式,好比你有一個fetchData(callback)的function用來獲取數據,而且在獲取完成的時候調用callback 函數,你想測試返回的數據是「peanut butter」 ,默認狀況下當fetchData執行完成的時候Jest的測試就完成了,這並非你所指望的那樣的去運行。框架

// Don't do this!
test('the data is peanut butter', () => {
  function callback(data) {
    expect(data).toBe('peanut butter');
  }

  fetchData(callback);
});

上面代碼的問題就在於一旦fetchData完成,測試也就執行完成,而後再調用回調。異步

Jest提供了一種用於測試的實現方式,下面代碼 done() 被執行則意味着callback函數被調用。 async

test('the data is peanut butter', done => {
  function callback(data) {
    expect(data).toBe('peanut butter');
    done();
  }

  fetchData(callback);
});

若是 done 永遠都不被調用,那麼的測試將會失敗,這也正是咱們指望的(咱們但願callback被調用,而且返回的data是咱們指望的值)函數

方法二:承諾驗證測試

若是你的代碼中使用了承諾的方式,處理異步測試將會變得更加簡單。Jest從你的測試中返回一個承諾,而後等待承諾被實現,若是沒有實現,那麼就判斷測試是失敗的。fetch

仍是上面的例子,若是用承諾驗證,那麼實現將是下面的樣子:this

test('the data is peanut butter', () => {
  expect.assertions(1);
  return fetchData().then(data => {
    expect(data).toBe('peanut butter');
  });
});

assertions(1)表明的是在當前的測試中至少有一個斷言是被調用的,不然斷定爲失敗。spa

若是刪掉return語句,那麼你的測試將在fetchData完成以前結束。

若是斷言的承諾並無被實現,那麼你能夠添加 .catch 方法。必定要添加expect,斷言驗證必定數量的斷言被調用。不然一個實現的承諾就不會失敗。

test('the fetch fails with an error', () => {
  expect.assertions(1);
  return fetchData().catch(e => expect(e).toMatch('error'));
});

在Jest 20.0.0+  的版本中你可使用 .resolves 匹配器在你的expect語句中,Jest將會等待一直到承諾被實現,若是承諾沒有被實現,測試將自動失敗。

test('the data is peanut butter', () => {
  expect.assertions(1);
  return expect(fetchData()).resolves.toBe('peanut butter');
});

若是你指望你的承諾是不被實現的,你可使用 .rejects ,它的原理和 .resolves相似

test('the fetch fails with an error', () => {
  expect.assertions(1);
  return expect(fetchData()).rejects.toMatch('error');
});

第三種:使用 Async/Await

我相信你們最Async/Await 是比較熟悉的,你能夠在測試中使用異步和等待。要編寫一個async測試,只需在傳遞到測試的函數前面使用async關鍵字。例如上面一樣的fetchData場景可使用下面的實現:

test('the data is peanut butter', async () => {
  expect.assertions(1);
  const data = await fetchData();
  expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  try {
    await fetchData();
  } catch (e) {
    expect(e).toMatch('error');
  }
});

固然你也能夠將Async Await和 .resolves  .rejects 結合起來(Jest 20.0.0+  的版本)

test('the data is peanut butter', async () => {
  expect.assertions(1);
  await expect(fetchData()).resolves.toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  await expect(fetchData()).rejects.toMatch('error');
});

寫在最後:

在這些狀況下,異步和等待實際上只是與承諾示例使用的相同邏輯的語法糖。


這幾種方法中沒有一個特別優於另一個,你能夠將它們組合在一個代碼庫中,甚至能夠在單個文件中進行匹配。它只是取決於哪一種樣式使你的測試更簡單。

 

系列教程:

   1. 前端測試框架Jest系列教程 -- Matchers(匹配器)

   2.前端測試框架Jest系列教程 -- Asynchronous(測試異步代碼)

   3.前端測試框架Jest系列教程 -- Mock Functions(模擬器)

   4.前端測試框架Jest系列教程 -- Global Functions(全局函數)

相關文章
相關標籤/搜索