前端测试框架Jest——语法篇
使用匹配器
使用不同匹配器可以测试输入输出的值是否符合预期。下面介绍一些常见的匹配器。
普通匹配器
最简单的测试值的方法就是看是否精确匹配。首先是toBe()
test('two plus two is four', () => {
expect( + ).toBe();
});
toBe用的是JavaScript中的Object.is(),属于ES6中的特性,所以不能检测对象,如果要检测对象的值的话,需要用到toEqual。toEquel递归检查对象或者数组中的每个字段。
test('object assignment', () => {
const data = {one: };
data['two'] = ;
expect(data).toEqual({one: , two: });
});
Truthiness
在实际的测试中,我们有时候需要区分undefined、null和false。以下的一些规则有助于我们进行。
- toBeNull只匹配null
- toBeUndefined只匹配undefined
- toBeDefine与toBeUndefined相反
- toBeTruthy匹配任何if语句为真
- toBeFalsy匹配任何if语句为假
数字匹配器
大多数的比较数字有等价的匹配器。
- 大于。toBeGreaterThan()
- 大于或者等于。toBeGreaterThanOrEqual()
- 小于。toBeLessThan()
- 小于或等于。toBeLessThanOrEqual()
- toBe和toEqual同样适用于数字 注意:对比两个浮点数是否相等的时候,使用toBeCloseTo而不是toEqual
例子如下:
test('two plus two', () => {
const value = + ;
expect(value).toBeGreaterThan();
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan();
expect(value).toBeLessThanOrEqual(4.5); // toBe and toEqual are equivalent for numbers
expect(value).toBe();
expect(value).toEqual();
});
test('两个浮点数字相加', () => {
const value = 0.1 + 0.2;
//expect(value).toBe(0.3); 这句会报错,因为浮点数有舍入误差
expect(value).toBeCloseTo(0.3); // 这句可以运行
});
如果使用toBe就会产生以下结果:

字符串
使用toMatch()测试字符串,传递的参数是正则表达式。
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
}); test('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/);
});
数组
如何检测数组中是否包含特定某一项?可以使用toContain()
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'beer',
]; test('购物清单(shopping list)里面有啤酒(beer)', () => {
expect(shoppingList).toContain('beer');
});
另外
如果你想在测试特定函数的时候抛出一个错误,在它调用的时候可以使用toThrow。
function compileAndroidCode() {
throw new ConfigError('you are using the wrong JDK');
} test('compiling android goes as expected', () => {
expect(compileAndroidCode).toThrow();
expect(compileAndroidCode).toThrow(ConfigError); // You can also use the exact error message or a regexp
expect(compileAndroidCode).toThrow('you are using the wrong JDK');
expect(compileAndroidCode).toThrow(/JDK/);
});
测试异步代码
在实际开发过程中,我们经常会遇到一些异步的JavaScript代码。当你有以异步方式运行的代码的时候,Jest需要知道当前它测试的代码是否已经完成,然后它可以转移动另一个测试。也就是说,测试用例一定要在测试对象结束之后才能够结束
为了达到这一目的,Jest有多种方法可以做到。
回调
最常见的异步模式就是回调函数。
注意:回调函数和异步没有必然的联系,回调只是异步的一种调用方式而已,不要将异步和回调两个概念结合起来谈
比如以下代码:
// 这里是同步执行的,完全没有异步
function fun1(callback) {
callback();
}
现在假设一个fetchData(call)函数,获取一些数据并在完成的时候调用call(data),而我想要测试返回的数据是不是字符串'peanut butter'
默认情况下,一旦到达运行上下文底部,jest测试就会立即结束。这意味着这个测试将不能按照预期的进行。
function fetchData(call) {
setTimeout(() => {
call('peanut butter1')
},);
} test('the data is peanut butter', () => {
function callback(data) {
expect(data).toBe('peanut butter'); // 这里没有执行到
// done()
}
fetchData(callback);
});
这样做是不会报错的,因为没有执行到我们想要测试的语句中的时候Jest测试已经结束了。(一旦fetchData执行结束,此测试就在没有调用回调函数前结束,因为使用了setTimeout,产生了异步)
而我们可以改成以下: 使用单个参数调用done,而不是将测试放在一个空参数的函数中,Jest会等done回调函数执行结束后,结束测试。
function fetchData(call) {
setTimeout(() => {
call('peanut butter1')
},);
} test('the data is peanut butter', (done) => {
function callback(data) {
expect(data).toBe('peanut butter');
done()
}
fetchData(callback);
});

如果done()永远不会被调用,则说明这个测试将失败,这也正是我们所希望看到的。
Promise
如果我们的代码中使用到了Promises,只需要从你的测试中返回一个Promise,Jest就会等待这个Promise来解决。如果承诺被拒绝,则测试将会自动失败。
举个例子,如果fetchData,使用Promise代替回调的话,返回值是应该解析为一个字符串'peanut butter'的Promise。那么我们可以使用以下方式进行测试代码:
test('the data is peanut butter', () => {
expect.assertions();
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});
注意:一定要返回Promise,如果省略了return语句,测试将会在fetchData完成之前完成。
另外一种情况,就是想要Promise被拒绝,我们可以使用.catch方法。另外,要确保添加了expect.assertions来验证一定数量的断言被调用。否则一个fulfilled态的Promise不会让测试失败。
test('the fetch fails with an error', () => {
expect.assertions();
return fetchData().catch(e => expect(e).toMatch('error'));
});
.resolves/.rejects
可以使用./resolves匹配器匹配你的期望的声明(跟Promise类似),如果想要被拒绝,可以使用.rejects
test('the data is peanut butter', () => {
expect.assertions();
return expect(fetchData()).resolves.toBe('peanut butter');
});
test('the fetch fails with an error', () => {
expect.assertions();
return expect(fetchData()).rejects.toMatch('error');
});
Async/Await
若要编写async测试,只要在函数前面使用async关键字传递到test。比如,可以用来测试相同的fetchData()方案
test('the data is peanut butter', async () => {
expect.assertions();
const data = await fetchData();
expect(data).toBe('peanut butter');
}); test('the fetch fails with an error', async () => {
expect.assertions();
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
}
});
setup and teardown
写测试的时候,我们经常需要进行测试之前做一些准备工作,和在进行测试后需要进行一些整理工作。Jest提供辅助函数来处理这个问题。
为多次测试重复设置
如果你有一些要为多次测试重复设置的工作,可以使用beforeEach和afterEach。
有这样一个需求,需要我们在每个测试之前调用方法initializeCityDatabase(),在每个测试后,调用方法clearCityDatabase()
beforeEach(() => {
initializeCityDatabase();
}); afterEach(() => {
clearCityDatabase();
}); test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
}); test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
一次性设置
在某些情况下,你只需要在文件的开头做一次设置。这种设置是异步行为的时候,你不太可能一行处理它。Jest提供了beforeAll和afterAll处理这种情况。
beforeAll(() => {
return initializeCityDatabase();
}); afterAll(() => {
return clearCityDatabase();
}); test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
}); test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
作用域
默认情况下,before和after的块可以应用到文件中的每一个测试。此外可以通过describe块来将将测试中的某一块进行分组。当before和after的块在describe块内部的时候,则只适用于该describe块内的测试。
比如说,我们不仅有一个城市的数据库,还有一个食品数据库。我们可以为不同的测试做不同的设置︰
// Applies to all tests in this file
beforeEach(() => {
return initializeCityDatabase();
}); test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
}); test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
}); describe('matching cities to foods', () => {
// Applies only to tests in this describe block
beforeEach(() => {
return initializeFoodDatabase();
}); test('Vienna <3 sausage', () => {
expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
}); test('San Juan <3 plantains', () => {
expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
});
});
注意:顶级的beforeEach描述块内的beforeEach之前执行,以下的例子可以方便我们认识到执行的顺序
beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));
test('', () => console.log('1 - test'));
describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'));
afterAll(() => console.log('2 - afterAll'));
beforeEach(() => console.log('2 - beforeEach'));
afterEach(() => console.log('2 - afterEach'));
test('', () => console.log('2 - test'));
}); // 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach //特别注意
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll
以上内容就是本篇的全部内容以上内容希望对你有帮助,有被帮助到的朋友欢迎点赞,评论。
如果对软件测试、接口测试、自动化测试、面试经验交流。感兴趣可以关注我,我们会有同行一起技术交流哦。
前端测试框架Jest——语法篇的更多相关文章
- 前端测试框架Jest系列教程 -- 简介
写在前面: 随着互联网日新月异的发展,用户对于页面的美观度,流畅度以及各方面的体验有了更高的要求,我们的网页不再是简单的承载文字,图片等简单的信息传递给用户,我们需要的是更加美观的页面展示,更快的浏览 ...
- 前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)
写在前面: 在JavaScript代码中,异步运行是很常见的.当你有异步运行的代码时,Jest需要知道它测试的代码何时完成,然后才能继续进行另一个测试.Jest提供了几种方法来处理这个问题. 测试异步 ...
- 前端测试框架Jest系列教程 -- Mock Functions
写在前面: 在写单元测试的时候有一个最重要的步骤就是Mock,我们通常会根据接口来Mock接口的实现,比如你要测试某个class中的某个方法,而这个方法又依赖了外部的一些接口的实现,从单元测试的角度来 ...
- 前端测试框架Jest系列教程 -- Global Functions(全局函数)
写在前面: Jest中定义了很多全局性的Function供我们使用,我们不必再去引用别的包来去实现类似的功能,下面将列举Jest中实现的全局函数. Jest Global Functions afte ...
- 前端测试框架Jest系列教程 -- Mock Functions(模拟器)
写在前面: 在写单元测试的时候有一个最重要的步骤就是Mock,我们通常会根据接口来Mock接口的实现,比如你要测试某个class中的某个方法,而这个方法又依赖了外部的一些接口的实现,从单元测试的角度来 ...
- 前端测试框架jest 简介
转自: https://www.cnblogs.com/Wolfmanlq/p/8012847.html 作者:Ken Wang 出处:http://www.cnblogs.com/Wolfmanlq ...
- 前端测试框架Jest系列教程 -- Matchers(匹配器)
写在前面: 匹配器(Matchers)是Jest中非常重要的一个概念,它可以提供很多种方式来让你去验证你所测试的返回值,本文重点介绍几种常用的Matcher,其他的可以通过官网api文档查看. 常用的 ...
- 前端测试框架Jest系列教程 -- Expect(验证)
写在前面 在编写测试时,我们通常需要检查值是否满足某些条件,Jest中提供的expect允许你访问很多“Matchers”,这些“匹配器”允许您验证不同的东西. Expect 可以验证什么 Jest中 ...
- 前端测试框架 Jest
前端测试工具一览 前端测试工具也和前端的框架一样纷繁复杂,其中常见的测试工具,大致可分为测试框架.断言库.测试覆盖率工具等几类.在正式开始本文之前,我们先来大致了解下它们: 测试框架 测试框架的作用是 ...
随机推荐
- PHP tempnam() 函数
定义和用法 tempnam() 函数在指定的目录中创建一个具有唯一文件名的临时文件. 该函数返回新的临时文件名,如果失败则返回 FALSE. 语法 tempnam(dir,prefix) 参数 描述 ...
- PHP imageantialias - 是否使用抗锯齿(antialias)功能
imageantialias — 是否使用抗锯齿(antialias)功能.高佣联盟 www.cgewang.com 语法 bool imageantialias ( resource $image ...
- PHP str_split() 函数
实例 把字符串 "Hello" 分割到数组中: <?php print_r(str_split("Hello")); ?>高佣联盟 www.cgew ...
- 5.15 省选模拟赛 容斥 生成函数 dp
LINK:5.15 T2 个人感觉生成函数更无脑 容斥也好推的样子. 容易想到每次放数和数字的集合无关 所以得到一个dp f[i][j]表示前i个数字 逆序对为j的方案数. 容易得到转移 使用前缀和优 ...
- SpringBoot之多模块项目
SpringBoot之多模块项目 说明:我们通过maven的父子工程来搭建springboot的多模块项目** 项目的整体结构 本项目涉及了到了五个模块 framework-web模块主要是放置前端的 ...
- Python 为什么会有个奇怪的“...”对象?
本文出自"Python为什么"系列,请查看全部文章 在写上一篇<Python 为什么要有 pass 语句?>时,我想到一种特别的写法,很多人会把它当成 pass 语句的 ...
- 【NOIP2013】火柴排队 题解(贪心+归并排序)
前言:一道水题. ----------------------- 题目链接 题目大意:给出数列$a_i$和$b_i$,问使$\sum_{i=1}^n (a_i-b_i)^2$最小的最少操作次数. 首先 ...
- 如何利用NLog输出结构化日志,并在Kibana优雅分析日志?
上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志),今天我们来看下如何向ES输出结构化日志.并利用Kibana中分析日志. NLog输出结构化日志 Elas ...
- Nexus3 上传的文件在哪里
上传文件 ojdbc7.jar,上传步骤略. 服务器上默认的文件存放路径是: nexus/sonatype-work/nexus3/blobs/default/content/ 一堆文件夹,根据时间确 ...
- Web测试转App测试不看不知道
Web测试 Web通常指的是互联网应用系统,比如税务电子化征管档案系统.金融数据平台.餐饮商家管理后台等等,其实质是C/S的程序. C是Client--客户端,S是Server--服务器. Web中的 ...