前言
折磨一下这个命令行小工具,这里使用的是jest,主要的测试内容是文件的读写能力
测试流程
- 创建
__tests__/db.spec.js - 明确目标,我们需要测试
fs的读写,因此要进行mock - 创建
__mocks__/fs.js - 写测试代码
- 运行测试
- 大功告成
代码分析
通过jest.mock()对fs进行mock
//__tests__/db.spec.js
const fs = require('fs')
jest.mock('fs')
这里使用了describe来测试
//__tests__/db.spec.js
describe('db', () => {
it('can read', () => {})
it('can write', () => {})
})
由于使用到了fake fs,因此我们要准备好假身的功能
//__mocks__/fs.js
//先将原有的功能全部复制给我们的fake fs
const fs = jest.createMockFromModule('fs')
const _fs = jest.requireActual('fs')
Object.assign(fs, _fs)
//准备测试readFile的功能
let readMocks = {}
fs.setReadFileMock = (path, error, data) => {
readMocks[path] = [error, data]
}
fs.readFile = (path, options, callback) => {
//options是可选参数,如果没有传的话,callback就是第二个参数
if (callback === undefined) callback = options
if (path in readMocks) {
callback(...readMocks[path])
} else {
_fs.readFile(path, options, callback)
}
}
//准备测试writeFile的功能
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)
}
}
假身准备完毕,开始写测试的主体
//__tests__/db.spec.js
describe('db', () => {
it('can read', async () => {
const data = [{title: 'hi', done: true}]
fs.setReadFileMock('/testRead', null, JSON.stringify(data))
const list = await db.read('/testRead')
expect(list).toStrictEqual(data)
})
it('can write', async () => {
let fakeFile = ''
fs.setWriteFileMock('/testWrite', (path, data, callback) => {
fakeFile = data
callback(null)
})
const list = [{title: "test1", done: true}, {title: "test2", done: false}]
await db.write(list, '/testWrite')
expect(fakeFile).toBe((JSON.stringify(list) + '\n'))
})
})
为了保障每条测试项都互不干扰,我们需要做一个clear的操作
//__mocks__/fs.js
fs.clearMocks = () => {
readMocks = {}
writeMocks = {}
}
//__tests__/db.spec.js
describe('db', () => {
afterEach(() => {
fs.clearMocks()
})
...
})
至此测试代码全部写完了。
后记
这是一个简单的单元测试,如果你有意见或建议,欢迎留言告诉我~