jest 简单使用

jest 简单使用

Apr 05, 2024 ·
9 Min Read

Jest 是一个 JavaScript 测试框架,是目前比较热门使用的测试框架之一。

中文文档

安装

Terminal window
npm install -D jest

如果你要生成 Jest 的基础配置文件,执行👇

Terminal window
npx jest --init

如果你要生成 Jest 的代码测试覆盖率,执行👇

Terminal window
npx jest --coverage

使用

首先新建一个 demo01.js,编写如下代码:

function sum(a, b) {
return a + b
}
module.exports = sum

然后再新建一个测试文件 demo01.test.js,编写如下代码:

const sum = require('./sum')
test('sum方法测试', () => {
expect(sum(1, 2)).toBe(3)
})

package.json 加入

{
"scripts": {
"test": "jest"
}
}

最后在控制台输入 npm run test

这时控制台会打印一条 PASS ./demo01.test.js。说明测试通过。

好了,上面这个小例子就是 Jest 的基本用法。

正文现在才开始😉😉😉

demo01.test.js 中我们看到有一个 test() 的方法,它是用来测试的,相当于一个测试用例。

test() 第一个参数是测试的描述,第二个参数是一个函数体,允许我们在函数体内进行编写测试代码

expect(value) 是每次测试一个值的时候都使用的函数,通常与匹配器一起使用,例如 demo01.test.js 中的 toBe(),它相当于 ===

这时候我们回头看看之前 demo01.test.js 的代码,应该就不难理解了

测试描述:sum方法测试

测试 sum(1, 2) 这个方法并传入参数1, 2,期望的值是否 === 3。

然后输出的结果是 PASS 表示 测试通过💯

常用的匹配器

// 部分匹配器 实例:
test('测试匹配', () => {
const a = {num: '007'}
expect(a).toBe(a)
}) // PASS
test('toEqual匹配', () => {
const a = {num: '007'}
expect(a).toEqual({num: '007'})
}) // PASS
// 注意:若这里使用toBe(),按数学而言0.1+0.2 === 0.3 这是没有问题的,但在Javascript中,因为设计问题,0.1+0.2 === 0.30000004,因此是 !== 0.3 的,所有这里使用 toBeCloseTo() 解决精度问题才能正确测试。
test('toBeCloseTo匹配', () => {
expect(0.1 + 0.2).toBeCloseTo(0.3)
}) // PASS

四个构子

作用域

钩子函数在父级分组可作用域子集,类似继承。

钩子函数同级分组作用域互不干扰,各起作用。

先执行外部的钩子函数,再执行内部的钩子函数。

注意

一个测试文件里,就相当于默认有一个分组,只是省略不见而已。

describe(name, fn) 分组,第一个参数分组名字,第二个参数是一个函数体,可以添加多个测试用例,即test()

// 构子 实例
beforeAll(() => {
console.log('执行在所有测试用例之前')
})
afterAll(() => {
console.log('执行在所有测试用例之后')
})
beforeEach(() => {
console.log('在每个测试用例执行之前都执行')
})
afterEach(() => {
console.log('在每个测试用例执行之后都执行')
})
test('测试1', () => {
console.log('开始测试1')
expect(sum(1, 2)).toBe(3)
})
test('测试2', () => {
console.log('开始测试2');
expect(sum(3, 3)).toBe(6)
})
jest
jest
// 作用域 实例
beforeAll(() => {
console.log('我是父组beforeAll')
})
afterAll(() => {
console.log('我是父组afterAll')
})
describe('这是分组1', () => {
beforeAll(() => {
console.log('我是分组1 beforeAll')
})
afterAll(() => {
console.log('我是分组1 afterAll')
})
test('测试1', () => {
console.log('分组1-测试1')
})
test('测试2', () => {
console.log('分组1-测试2')
})
})
describe('这是分组2', () => {
beforeAll(() => {
console.log('我是分组2 beforeAll')
})
afterAll(() => {
console.log('我是分组2 afterAll')
})
test('测试1', () => {
console.log('分组2-测试1')
})
test('测试2', () => {
console.log('分组2-测试2')
})
})
jest
jest

‼️坑点

细心的人会发现,在我们编写的 demo01.jsdemo01.test.js 文件中,我们都是使用 commonJs 语法(对于还不知道 commonJs 语法是什么的,自行百度,这里就不多说了),但现在基本前端项目都是使用了 Es module 语法。这是 Jest 不支持的

但可以使用 Babel 进行语法转换,首先安装 Babel👇

Terminal window
npm install -D @babel/core @babel/preset-env

然后在项目根目录新建babel 配置文件 .babelrc

{
"presets": [
["@babel/preset-env", {
"targets": {
"node": "current"
}
}]
]
}

这时您就可以放心使用 Es module 语法啦~~~

异步代码测试

1️⃣第一个坑点:异步回调测试

默认jest 只把代码能执行就表示为通过了,即不会等异步代码执行完毕,但我们可以通过传入回调中的 done参数,来表示何时检查结束。类似新版gulp语法。

demo02.js
function fetchXxx(fn) {
fetch('http://xxx.json').then(res => {
fn(res)
})
}
demo02.test.js
// 错误写法
test('fetchXxx 测试', () => {
fetchXxx(data => {
expect(data).toEqual({
success: true
})
})
}) // PASS
// 最后会输出 pass,这不就是对了吗?不,它是无论什么都会测试通过,你可以尝试把 请求地址 改为错误的,它一样 PASS,因为它这里不会等待请求回来(即异步处理完毕),它只有能把 请求 发出去了就表示测试通过了,这很明显不符合我们想要的测试需求。因此我们可以在 test() 方法的 第二个参数 fn 中传入 done,在我们想要测试的结束处执行 done() 即可。 如下
// 正确写法
test('fetchXxx 测试', done => {
fetchXxx(data => {
expect(data).toEqual({
success: true
})
done()
})
}) // PASS

2️⃣第二个坑点:返回一个未处理的 promise

demo03.js
function fetchXxx() {
return fetch('http://xxx.json')
}
demo03.test.js
// 错误写法
test('fetchXxx 测试', () => {
fetchXxx().then(data => {
expect(data).toEqual({
success: true
})
})
}) // PASS,原因与第一个坑点一样,无论何时都是 PASS
// 正确写法
test('fetchXxx 测试', () => {
return fetchXxx().then(data => {
expect(data).toEqual({
success: true
})
})
})
// PS: 可以不使用 return, 也可以使用 async/await

3️⃣第三个坑点:异步捕获异常

demo04.js
function fetchXxx() {
return fetch('http://xxx.json')
}
demo04.test.js
// 错误写法
test('fetchXxx 测试', () => {
return fetchXxx().catch(e => {
expect(e.toString().indexOf('404') > -1).toBe(true)
})
}) // PASS
// 看似没有问题, return 也做了,但实际上它也是无论什么时候都返回 PASS。
// 正确写法
test('fetchXxx 测试', () => {
expect.assertions(1) // 若没有这句,无论是否有异常都表示测试通过
return fetchXxx().catch(e => {
expect(e.toString().indexOf('404') > -1).toBe(true)
})
}) // PASS
// expect.assertions(value) 表示断言,value表示 expect至少要执行多少次

简单使用 Jest 就到此结束了,学会了吗???🤨🤨🤨

Last edited Feb 15