jest 前端测试框架

  1. 环境搭建
1
2
3
mkdir JestTest
cd JestTest
npm install jest --save-dev
  1. 测试文件

以.test 文件来命名,如新建一个 sum.js,要测试这个文件需建一个 sum.test.js 文件作为入口。
jest 提供的两个方法:

  • test 方法:Jest 封装的测试方法,一般填写两个参数,描述和测试方法

  • expect 方法 :预期方法,就是你调用了什么方法,传递了什么参数,得到的预期是什么。

1
2
3
4
5
6
7
8
9
10
11
12
13
// sum.js
const sum = (a, b) => {
return a + b;
};
module.exports = {
sum,
};

// sum.test.js
const { sum } = require("./sum.js");
test("计算总和", () => {
expect(sum(2, 3)).toBe(5);
});
  1. 初始化配置和生成测试覆盖率文件
1
npx jest --init

生成一个说明文件:

1
npx jest --coverage
  1. 匹配器

    toBe()匹配器

toBe()匹配器,是在工作中最常用的一种匹配器,简单的理解它就是相等。这个相当是等同于===的,也就是我们常说的严格相等。

1
2
3
4
5
test("测试严格相等", () => {
const a = { number: "007" };
expect(a).toBe({ number: "007" });
});
// 报错

toEqual()匹配器

相当于==

1
2
3
4
test("测试严格相等", () => {
const a = { number: "007" };
expect(a).toEqual({ number: "007" });
});

toBeNul()匹配器

toBeNull()匹配器只匹配null值,需要注意的是不匹配undefined的值。

1
2
3
4
test("toBeNull测试", () => {
const a = null;
expect(a).toBeNull();
});

toBeUndefined()匹配器

toBeUndefined()匹配 undefined

1
2
3
4
test("toBeUndefined测试", () => {
const a = undefined;
expect(a).toBeUndefined();
});

toBeDefined()匹配器

toBeDefined()定义过了就匹配,这里注意的是 null 值可以通过测试

1
2
3
4
test("toBeDefined测试", () => {
const a = "sheri";
expect(a).toBeDefined();
});

toBeTruthy()匹配器

返回 true 才能测试通过

1
2
3
4
5
6
7
8
9
10
11
test("toBeTruthy 测试", () => {
const a = 0;
expect(a).toBeTruthy();
});
// 不通过

test("toBeTruthy 测试", () => {
const a = "sheri";
expect(a).toBeTruthy();
});
// 通过

toBeFalsy()匹配器

返回 false 就测试通过

1
2
3
4
test("toBeFalsy 测试", () => {
const a = 0;
expect(a).toBeFalsy();
});

toBeGreaterThan()匹配器

这个是用来作数字比较的,大于什么数值,只要大于传入的数值,就可以通过测试。

1
2
3
4
test("toBeGreaterThan匹配器", () => {
const count = 10;
expect(count).toBeGreaterThan(9);
});

toBeLessThan()匹配器

toBeLessThantoBeGreaterThan相对应的,就是少于一个数字时,就可以通过测试。

1
2
3
4
test("toBeLessThan匹配器", () => {
const count = 10;
expect(count).toBeLessThan(11);
});

toBeGreaterThanOrEqual()匹配器

当测试结果数据大于等于期待数字时,可以通过测试。

1
2
3
4
5
6
7
8
9
10
11
test("toBeGreaterThan匹配器", () => {
const count = 10;
expect(count).toBeGreaterThan(10);
});
// 报错

test("toBeGreaterThanOrEqual匹配器", () => {
const count = 10;
expect(count).toBeGreaterThanOrEqual(10);
});
// 通过

toBeLessThanOrEqual()匹配器

与上相反

toBeCloseTo()匹配器

这个是可以自动消除JavaScript浮点精度错误的匹配器,举个例子,比如我们让0.10.2相加,这时候js得到的值应该是0.30000000000004,所以如果用toEqual()匹配器,测试用例会通过不了测试的。

1
2
3
4
5
6
7
8
9
10
11
12
13
test("toEqual匹配器", () => {
const one = 0.1;
const two = 0.2;
expect(one + two).toEqual(0.3);
});
// 报错

test("toBeCloseTo匹配器", () => {
const one = 0.1;
const two = 0.2;
expect(one + two).toBeCloseTo(0.3);
});
// 通过

toMatch()匹配器

字符串包含匹配器

1
2
3
4
5
6
7
8
9
10
test("toMatch匹配器", () => {
const str = "谢大脚、刘英、小红";
expect(str).toMatch("谢大脚");
});

// 正则也可以
test("toMatch匹配器", () => {
const str = "谢大脚、刘英、小红";
expect(str).toMatch(/谢大脚/);
});

toContain()匹配器

字符串包含关系,和上面的区别,这个是数组的匹配器

1
2
3
4
5
6
7
8
9
10
test("toContain匹配器", () => {
const arr = ["谢大脚", "刘英", "小红"];
expect(arr).toContain("谢大脚");
});
// set也可以兼容
test("toContain匹配器", () => {
const arr = ["谢大脚", "刘英", "小红"];
const data = new Set(arr);
expect(data).toContain("谢大脚");
});

toThrow()匹配器

专门对异常进行处理的匹配器,可以检测一个方法会不会抛出异常。

1
2
3
4
5
6
7
8
9
10
11
12
const throwNewErrorFunc = () => {
throw new Error("this is a new error");
};

test("toThrow匹配器", () => {
expect(throwNewErrorFunc).toThrow();
});

// 也可加一些字符串匹配,但是字符串必须对应
test("toThrow匹配器", () => {
expect(throwNewErrorFunc).toThrow("this is a new error");
});

not()匹配器

not匹配器是Jest中比较特殊的匹配器,意思就是相反或者说取反。

1
2
3
4
5
6
7
8
const throwNewErrorFunc = () => {
throw new Error("this is a new error");
};

test("toThrow匹配器", () => {
expect(throwNewErrorFunc).not.toThrow();
});
// 不能通过

还有很多匹配器,可以找官方文档https://jestjs.io/docs/en/expect

  1. 异步代码测试方法

    回调函数式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// fetchData.js
import axios from "axios";

export const fetchData = (fn) => {
axios.get("http://a.jspang.com/jestTest.json").then((response) => {
fn(response.data);
});
};
// fetchData.test.js
import { fetchData } from "./fetchData.js";

test("fetchData 测试", () => {
fetchData((data) => {
expect(data).toEqual({
success: true,
});
done();
});
});

返回 promise

1
2
3
4
5
6
7
8
9
10
11
export const fetchTwoData = () => {
return axios.get("http://a.jspang.com/jestTest.json");
};
import { fetchData, fetchTwoData } from "./fetchData.js";
test("FetchTwoData 测试", () => {
return fetchTwoData().then((response) => {
expect(response.data).toEqual({
success: true,
});
});
});

走 catch 错误方法,只有出现异常的时候才会走这个方法,而现在没有出现异常,就不会走这个测试方法,所以走正常的测试用例会通过测试,这时候需要执行一次断言

1
2
3
4
5
6
test("FetchThreeData 测试", () => {
expect.assertions(1); // 断言,必须执行一次expect
return fetchThreeData().catch((e) => {
expect(e.toString().indexOf("404") > -1).toBe(true);
});
});

async…await

这时候我们的代码使用async....await...的形式,这里我们还使用了resolves用于把现有对象转换成Promise对象,然后使用Jest中的toMatchObject进行匹配对象中的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
test("FetchFourData 测试", async () => {
//resolves把现有对象转换成Promise对象,
//toMatchObject 匹配对象中的属性
await expect(fetchFourData()).resolves.toMatchObject({
data: {
success: true,
},
});
});
// 简单一点的方法
test("FetchFourData 测试", async () => {
const response = await fetchFourData();
expect(response.data).toEqual({
success: true,
});
});
  1. jest 的四个钩子函数

    beforeAll

在所有测试用例之前进行执行。

1
2
3
4
beforeAll(() => {
console.log("beforeAll Test");
});
// 控制台会先输出'beforeAll Test',再执行后面的用例

afterAll

在完成所有测试用例之后才执行。

1
2
3
afterAll(() => {
console.log("afterAll Test");
});

beforeEach

在每个测试用例前都会执行一次的钩子函数。

1
2
3
beforeEach(() => {
console.log("beforeEach Test");
});

afterEach

在每次测试用例完成测试之后执行一次。

1
2
3
afterEach(() => {
console.log("afterEach Test");
});
  1. 测试用例分组

Jest为我们提供了一个分组的语法describe(),这个方法接受两个参数,可以把多个测试用例进行分开。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe("大脚相关服务", () => {
test("测试 大脚足浴 方法", () => {
baojian.gongzhu(1);
baojian.anjiao();
console.log(baojian.fuwu);
expect(baojian.fuwu).toEqual("大脚走进房间为你_足疗");
});

test("测试 大脚泰式保健 方法", () => {
baojian.gongzhu(1);
baojian.taishi();
console.log(baojian.fuwu);
expect(baojian.fuwu).toEqual("大脚走进房间为你_泰式保健");
});
});
  1. 钩子函数的作用域
  • 钩子函数在父级分组可作用域子集,类似继承
  • 钩子函数同级分组作用域互不干扰,各起作用
1
2
3
4
5
6
7
8
9
10
11
12
describe("test1", () => {
beforeEach(() => {
console.log("beforeEach Test1");
});
});
describe("test2", () => {
beforeEach(() => {
console.log("beforeEach Test2");
});
});
// beforeEach Test1
// beforeEach Test2
  • 先执行外部的钩子函数,再执行内部的钩子函数