在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(测试异步代码)