前端测试框架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(全局函数)

相关文章
相关标签/搜索