mocha、chai和supertest单元测试
mocha单元测试
1. 因为有时候在代码中加了新的东西需要反复测试接口 或者 别人要求 重新跑接口非常的繁琐
2. 所有我们需要一个帮我们重复测试的东西 那就是mocha
3. 先下载 一定不要全局安装 不然后期如果这个模块更新有问题影响的是全部的文件
npm i mocha
4. 因为不是全局安装 没办法通过命令直接获取我们还得去 根目录下找bin文件太繁琐了 所以我们需要配置 pakeage.json文件里的内容 改脚本内的 test 起其他名字也行
{ ---------------------------- 初始化内容 "name": "mocah", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { // ---------改这里 "test": "mocha" },--------------------------end "author": "", "license": "ISC", "dependencies": { ----------这个是后面案例需要的 包 "chai": "^4.3.6", "koa": "^2.13.4", "mocha": "^10.0.0", "supertest": "^6.2.4" } }
5. 如果执行的话直接 npm test 如果你不是 test最好加上 npm run 名字 这个会直接找你文件夹下的 test文件 这个和上面的 npm test 没有关联!!! mocha这个模块会找 名字带有test 文件的名字
6.封装一个方法方便演示
function maxNum(...arr) { return arr.length ? Math.max(...arr) : 0; //就是取传来的最大值 没有传值就返回0 } module.exports = maxNum; //导出
7. 编写测试 用的是node 自带的配合mocha 它还提供了describe 和it 方法非常的好用 具体看代码
const maxNum = require("../maxNum"); const assert = require("assert"); describe("第一组测试", () => { describe("小测试1", () => { it("sum() 结果 0 ", () => { // 这个是node 内置的 assert测试 strictEqual表示严格模式下 assert.strictEqual(maxNum(), 0);//断言 在严格模式下maxNum()结果是0 }); }); describe("小的测试2", () => { it("sum(1) 结果 1", () => { // 这个是node 内置的 assert测试 strictEqual表示严格模式下 assert.strictEqual(maxNum(1), 2); // 专门写错一个 }); }); }); // 第二组大的测试 describe("第二组大的测试", () => { it("sum(1,2) 结果 2 ", () => { // 这个是node 内置的 assert测试 strictEqual表示严格模式下 assert.strictEqual(maxNum(1, 2), 2); //断言在严格模式下 maxNum(1,2)值是2 }); it("sum(1,2,3) 结果 3", () => { // 这个是node 内置的 assert测试 strictEqual表示严格模式下 assert.strictEqual(maxNum(1, 2, 3), 3);//断言在严格模式下 maxNum(1,2,3)值是3 }); }); -------------------------------------结果--------------------- 第一组测试 小测试1 ✔ sum() 结果 0 小的测试2 1) sum(1) 结果 1 第二组大的测试 ✔ sum(1,2) 结果 2 ✔ sum(1,2,3) 结果 3 3 passing (21ms) 1 failing 1) 第一组测试 小的测试2 sum(1) 结果 1: AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: 1 !== 2 + expected - actual -1 +2 at Context.<anonymous> (test\test.js:14:14) at processImmediate (node:internal/timers:466:21)
chai 可以更加方便也比node 自带的功能 要更加强大
官网 :https://www.chaijs.com/
1. 它还整合了需要其他模块的风格 比如 expect 风格 assert风格 should 风格等多种风格
2. 下载安装 chai
npm install chai
3. assert 风格
const maxNum = require("../maxNum"); //导入上面那个函数 const chai = require("chai"); //导入下载好的模块 const assert = chai.assert;// 用这个模块中的assert方法 describe("测试", () => { it("使用 assert 风格", () => { assert.equal(maxNum(1, 5, 2), 5);// 表示断言maxNum(1,5,2)结果是 5 assert.typeOf(maxNum(1, 5, 2), "Number");// 断言maxNum(1,5,2)结果应该是个Number }); }); --------------------------log-------------- 测试 ✔ 使用 assert 风格 1 passing (12ms)
4.should风格 这种链式调用的风格的
const maxNum = require("../app"); const chai = require("chai"); chai.should(); // 调用一下 describe("测试", () => { it("使用 should 风格", () => { //这个函数应该存在并且值等于1 并且值是 Number类型 maxNum(1).should.exist.and.equal(1).and.be.a("Number"); // 分开写也行 maxNum(1).should.equal(1); // 值是1 maxNum(1).should.exist; // 应该存在 maxNum(1).should.be.a("Number"); // 应该是Number类型 }); }); -----------------------log--------------------------------- 测试 ✔ 使用 should 风格 1 passing (11ms)
5.expect 风格的 这种期望风格的
const maxNum = require("../app"); const chai = require("chai"); const expect = chai.expect; describe("测试", () => { it("使用 expect 风格", () => { // 期望这个值是 存在的 expect(maxNum(1)).to.exist; //期望它是个Number类型 expect(maxNum(1)).to.be.a("Number"); // 期望它的值是1 expect(maxNum(1)).to.equal(1); }); }); -----------------------------------------log ----------------- ✔ 使用 expect 风格 1 passing (12ms)
异步测试
1. 在好多情况下 比如接口 去操作数据库 去读取文件都是异步在上面那些异步就不好用了
2. 可以使用回调函数 不管演示的 是promise 用async await 方法实现异步测试
3. 异步读取文件
const chai = require("chai"); // 引入fs 模块 把他改装为promises对象来处理异步 或者你可以写成回调函数 const fs = require("fs").promises; const assert = chai.assert; // 异步读取文件 describe("测试异步", () => { it("读取文件", async () => { // 异步读取文件 等待文件读取成功才能进行抛出判断 let data = await fs.readFile("./my.text"); assert.equal(data, "111");//断言这个文件中的数据是111 }); }); ----------------------------------------log 测试异步 ✔ 读取文件 1 passing (14ms)
4.异步测试接口 这里我们用到是 supertest 这个小模块
4.1 下载安装supertest
npm install supertest
4.2 这个模块可以发送网络请求还有集成的断言 非常的好用
const koa = require("koa"); //引入koa模块 const app = new koa(); // 发get 请求就发送 json {ok:1} app.use((ctx, next) => { ctx.body = { ok: 1 }; }); // 把ap导出去 module.exports = app; -----------------------------------上面是创建服务器模块 不在同一个文件夹------------ const supertest = require("supertest"); // 导入模块 const app = require("../app"); //引入app describe("接口测试", () => { let server; it("测试get接口", async () => { await supertest(server) // 用async await 等待测试结果 .get("/")//发起get 请求 .expect(200, { ok: 1 }); // 进行判断看是ok:1吗 }); // 钩子函数在所有测试跑之前执行 before(() => { // 开启服务器 server = app.listen(3000); }); // 钩子函数在所有测试跑完之后执行 after(() => { // 关闭服务器 server.close(); }); });
钩子函数
1. 在一个大 的describe作用域中 before是所有测试之前 after 是所有请求之后
2. beforeEach是 每一个小的测试之前 afterEach是每一个小的测试之后
3. 这个就可以很方便的 比如 开启数据库 打开服务器等等 在不同的地方干不同的事件
after(() => { // 关闭服务器 server.close(); }); }); 钩子函数 const assert = require("chai").assert; const str = "test"; describe("测试钩子函数1", () => { it("测试它的数据类型是不是 string", () => { assert.typeOf(str, "string"); }); it("测试它值是不是 test", () => { assert.equal(str, "test"); }); // 定义钩子函数 beforeEach(() => { console.log("我是每一个函数1测试之前的"); }); afterEach(() => { console.log("我是每一个函数1测试之后的"); }); // 全部测试之前和之后 before(() => { console.log("我是函数1之前的"); }); after(() => { console.log("我是函数1之后的 "); }); }); describe("测试钩子函数2", () => { it("测试它的数据类型是不是 存在呀", () => { assert.exists(str); }); it("断言它值不是 数字 ", () => { assert.isNotNumber(str); }); // 定义钩子函数 beforeEach(() => { console.log("我是每一个函数2测试之前的"); }); afterEach(() => { console.log("我是每一个函数2测试之后的"); }); // 全部测试之前和之后 before(() => { console.log("我是函数2之前的"); }); after(() => { console.log("我是函数2之后的 "); }); });
-------------------------------log------------------
测试钩子函数1
我是函数1之前的
我是每一个函数1测试之前的
✔ 测试它的数据类型是不是 string
我是每一个函数1测试之后的
✔ 测试它值是不是 test
我是函数1之后的
测试钩子函数2
我是函数2之前的
我是每一个函数2测试之前的
✔ 测试它的数据类型是不是 存在呀
我是每一个函数2测试之后的
我是每一个函数2测试之前的
✔ 断言它值不是 数字
我是每一个函数2测试之后的
我是函数2之后的
4 passing (37ms)