写在前面:

  在JavaScript代码中,异步运行是很常见的。当你有异步运行的代码时,Jest需要知道它测试的代码何时完成,然后才能继续进行另一个测试。Jest提供了几种方法来处理这个问题。

测试异步代码的三种实现方式:

方法一:回调函数

这是非常常见的通用处理方式,比如你有一个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函数被调用。

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

如果 done 永远都不被调用,那么的测试将会失败,这也正是我们期望的(我们希望callback被调用,并且返回的data是我们期望的值)

方法二:承诺验证

如果你的代码中使用了承诺的方式,处理异步测试将会变得更加简单。Jest从你的测试中返回一个承诺,然后等待承诺被实现,如果没有实现,那么就判断测试是失败的。

还是上面的例子,如果用承诺验证,那么实现将是下面的样子:

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

assertions(1)代表的是在当前的测试中至少有一个断言是被调用的,否则判定为失败。

如果删掉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(全局函数)

前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)的更多相关文章

  1. 前端测试框架Jest系列教程 -- 简介

    写在前面: 随着互联网日新月异的发展,用户对于页面的美观度,流畅度以及各方面的体验有了更高的要求,我们的网页不再是简单的承载文字,图片等简单的信息传递给用户,我们需要的是更加美观的页面展示,更快的浏览 ...

  2. 前端测试框架Jest系列教程 -- Matchers(匹配器)

    写在前面: 匹配器(Matchers)是Jest中非常重要的一个概念,它可以提供很多种方式来让你去验证你所测试的返回值,本文重点介绍几种常用的Matcher,其他的可以通过官网api文档查看. 常用的 ...

  3. 前端测试框架Jest系列教程 -- Mock Functions

    写在前面: 在写单元测试的时候有一个最重要的步骤就是Mock,我们通常会根据接口来Mock接口的实现,比如你要测试某个class中的某个方法,而这个方法又依赖了外部的一些接口的实现,从单元测试的角度来 ...

  4. 前端测试框架Jest系列教程 -- Global Functions(全局函数)

    写在前面: Jest中定义了很多全局性的Function供我们使用,我们不必再去引用别的包来去实现类似的功能,下面将列举Jest中实现的全局函数. Jest Global Functions afte ...

  5. 前端测试框架Jest系列教程 -- Expect(验证)

    写在前面 在编写测试时,我们通常需要检查值是否满足某些条件,Jest中提供的expect允许你访问很多“Matchers”,这些“匹配器”允许您验证不同的东西. Expect 可以验证什么 Jest中 ...

  6. 前端测试框架Jest系列教程 -- Mock Functions(模拟器)

    写在前面: 在写单元测试的时候有一个最重要的步骤就是Mock,我们通常会根据接口来Mock接口的实现,比如你要测试某个class中的某个方法,而这个方法又依赖了外部的一些接口的实现,从单元测试的角度来 ...

  7. 前端测试框架jest 简介

    转自: https://www.cnblogs.com/Wolfmanlq/p/8012847.html 作者:Ken Wang 出处:http://www.cnblogs.com/Wolfmanlq ...

  8. 前端测试框架 Jest

    前端测试工具一览 前端测试工具也和前端的框架一样纷繁复杂,其中常见的测试工具,大致可分为测试框架.断言库.测试覆盖率工具等几类.在正式开始本文之前,我们先来大致了解下它们: 测试框架 测试框架的作用是 ...

  9. 转载自-阮一峰-测试框架 Mocha 实例教程

    测试框架 Mocha 实例教程   作者: 阮一峰 日期: 2015年12月 3日 Mocha(发音"摩卡")诞生于2011年,是现在最流行的JavaScript测试框架之一,在浏 ...

随机推荐

  1. JAVA基础知识总结:五

    一.初步认识数组 1.理解数组 数组是用来存储相兼容数据类型的定长的容器 特点: a.只能存放相兼容数据类型,不能存放多种数据类型 b.可以存放基本数据类型和引用数据类型 c.数组是定长的,一旦被初始 ...

  2. Nodejs.热部署方法

    在开发中我们修改了一点代码后要去重启服务器才能看到结果,为了省去这个过程我们以往经常使用热部署代码的方法 下面是使用"supervisor"来达到热部署能力的方法: sudo np ...

  3. Java基础-运算符(03)

    概念: 运算符:就是对于常量和变量进行操作的符号. 表达式:用运算符连接起来的符合java语法的式子,不同的运算符连接的表达式是不同类型的表达式. 运算符分类: 算数运算符(+  -  *  /  % ...

  4. spring mvc+mybatis+maven集成tkmapper+pagehelper

    <!-- maven tkmapper引入--> <dependency> <groupId>tk.mybatis</groupId> <arti ...

  5. spark的sparkUI如何解读?

    spark的sparkUI如何解读? 以spark2.1.4来做例子 Job - schedule mode 进入之后默认是进入spark job 页面 这个说明有很详细的解释,spark有两种操作算 ...

  6. chromium源码阅读--进程间通信(IPC)

    第一篇就有提到Chromium是目前默认是采用多进程架构,当然,chromium有singe-process的版本. 多进程与多线程的区别,确实有很多可以讲的,我的另一篇博客也讲了一些,这里是从浏览器 ...

  7. MQTT——编写连接报文

    笔者在上一章对连接报文进行了相关的讲解.这一章笔者想写一个连接报文的例子来加深理解.本来这一章也应该在上一章出现的.可是笔者怕太长了.不好方便阅.所以决定分俩章来.正如笔者上一章所讲的.笔者会用Net ...

  8. Sequence one

    Problem Description Search is important in the acm algorithm. When you want to solve a problem by us ...

  9. 关于狄克斯特拉算法(dijkstra)总结

    1,2,4是四个定点其他的是距离,从2到4最直接的就是2-4,但是不是最近的,需要舒展一下2-1-4,这样只有8.所以才是最短的.这个过程就是狄克斯特拉算法.下面进入正题:   我们这里定义图的编号为 ...

  10. js里面的map、filter、forEach、reduce、for in、for of等遍历方法

    1.map 遍历数组,改变原数组 [2, 3, 4, 5].map(function(val, key,arr) { return val > 3; }) var data = [ { name ...