1、引用jest
yarn add --dev jest
//package.json
{
"scripts": {
"test": "jest"
}
}
2、建测试文件
__tests__ 文件夹放测试文件;
xxx.spec.js 测试文件名字一般用 spec ;
// db.spec.js
const db = require('../db.js')
describe('db',()=>{
it('can read',()=>{
expect(db.read instanceof Function ).toBe(true)
})
it('can write',()=>{
expect(db.write instanceof Function).toBe(true)
})
})
3、mock 数据
__test__ 文件夹
//db.spec.js //名字一般用 spec
const db = require("../db.js")
const fs = require("fs") //这是 node.js 的 fs 模块
jest.mock("fs") //jest 接管了 fs 模块,后面的代码操作的都是 mock 后的 fs ;
describe("db", () => {
//mock 完了之后,要清除 mock ,否则测试用例之间会相互干扰;
//afterEach() 会在每一次 it 测试之后都执行
//fs.clearMocks();
afterEach(()=>{
fs.clearMocks()
})
it("can read", async () => {
const data = [{title: "hi", done: true}]
//因为 db.read 调用的是 fs.readFile
//通过 fs.setReadFileMock 改写 fs.readFile
//使得任何人访问 '/xxx' ,得到的内容都是一个数组的 JSON 序列化,fs 只能读取字符串
fs.setReadFileMock("/xxx", null, JSON.stringify(data))
const list = await db.read("/xxx")
expect(list).toStrictEqual(data)
})
//测试写文件时,因为单元测试是不能和外界打交道的,所以不能真的写文件
//而是在写文件时,不把它写到文件里面,而是写在变量里面。
it("can write", async () => {
let fakeFile
fs.setWriteFileMock("/yyy", (path,data,callback) => {
fakeFile = data
callback(null)
})
const list = [{title:'写博客',done:false},{title:'做项目',done:false}]
await db.write(list,'/yyy')
expect(fakeFile).toBe(JSON.stringify(list)+'\n')
})
})
__mocks__文件夹
//fs.js
const fs = jest.createMockFromModule('fs'); //将 mock 出来的 fs 模块放在 fs 中
const _fs = jest.requireActual('fs') // 将 node 的 fs 模块放在 _fs 中;
Object.assign(fs,_fs) //将 _fs 复制到 fs ;
let readMocks = {}
fs.setReadFileMock = (path, error, data)=>{ //篡改 fs.readFile
readMocks[path] = [error,data]
}
//fs.readFile(path,fn) 调用 fs.readFile 时,有可能只传了两个参数,需要判断下 callback === undefined;
fs.readFile = (path,options,callback)=>{ //fs 的其它属性都是复制 _fs 的,只改写了 fs.readFile();
if(callback === undefined) callback = options
if(path in readMocks){
callback(...readMocks[path]) //如果是 mock 的数据,就调用 readMocks[path] 的第一个参数 error 和第二个参数 data;
}else{
_fs.readFile(path,options,callback) //如果不是 mock 的数据,就调用 node.js 的 fs.readFile()
}
}
let writeMocks = {}
fs.setWriteFileMock = (path,fn)=>{
writeMocks[path] = fn
}
fs.writeFile = (path,data,options,callback) =>{
if(path in writeMocks){
writeMocks[path](path,data,options,callback)
}else{
_fs.writeFile(path,data,options,callback)
}
}
//mock 完之后要清除 mock,否则测试用例之间会相互干扰
fs.clearMocks = ()=>{
readMocks = {}
writeMocks = {}
}
module.exports = fs;