无法在Node.js单元测试中模拟文件系统
我有一个用nodejs编写的简单模块,该模块使用fs-extra
包测试文件是否存在.当路径存在时,模块将抛出该异常,否则将继续执行下一个过程.这是源文件:
I have a simple module written in nodejs that uses fs-extra
package to test if a file exists. The module throws when the path exists and proceed to next procedure otherwise. Here is the source file:
// - main.js -
import fs from 'fs-extra'
export default async (pathName) => {
// Do not procceed if path already exists.
if (await fs.pathExists(projectPath)) {
throw new Error(chalk.red.bold(`${projectPath} already exists`))
}
// more logic here
}
我想编写一个测试波纹管逻辑的单元测试:
I want to write a unit test that tests the bellow logic:
- 如果文件路径存在,我们希望抛出错误
我不想弄乱实际的文件系统(以防我的代码包含一些可能破坏它的讨厌的错误),所以我转到了另一种解决方案,使用mock-fs
模拟文件系统.这是规格文件:
I don't want to mess up with the real filesystem -in case my code contains some nasty bug that could destroy it- so I went to an alternative solution, mocking the filesystem using mock-fs
. Here is the spec file:
// - main.js spec file -
import mainFunction from '../main'
import mockfs from 'mock-fs'
describe('test main function', () => {
beforeEach(() => {
mockfs({
home: {
user: {
dummy: {}
}
}
})
})
test('expect to throw', async () => {
await mainFunction('/home/user/dummy')
})
afterEach(() => {
mockfs.restore()
})
})
出什么问题了?
每次运行测试时,主函数都不会抛出.发生这种情况是因为在规范文件中声明了mockfs
伪文件系统,因此主源文件中的fs
模块不知道mockfs
伪文件系统,并检查了真实文件系统.在我的真实文件系统中没有名为/home/user/dummy
的文件夹时,检查始终失败.
What's the problem?
Every time I run the test, the main function does not throw. This happens because mockfs
fake-filesystem was declared in the spec file, so the fs
module in main source file does not know for the mockfs
fake-filesystem and checks the real one. By the time that I do not have a folder named /home/user/dummy
in my real filesystem the check always fails.
mainFunction
应该抛出
mainFunction
不会抛出
我想我可以将这个单元测试变成一个集成测试.但我不想.有没有解决办法?我是否必须使用其他软件包? 我的测试服是 Jest 22.3.0 .
I guess that I can turn this unit test into an integration test. But I do not want to. Is there any fix for this? Do I have to use another packages? My test suit is Jest 22.3.0.
经过一番搜索,我找到了对分支进行单元测试的适当方法.我们确实不必使用mock-fs
模块.我们只需要模拟fs-extra
模块的pathExists
方法来返回值false
一次和值true
一次.贝娄,我发布了我的规格文件的工作版本:
After some search, I found the appropriate way to unit test the branch. We really do not have to use the mock-fs
module. We just have to mock pathExists
method of fs-extra
module to return one time the value false
and one time the value true
. Bellow, I post a working version of my spec file:
import mainFunction from '../main'
require('fs-extra').pathExists = jest.fn().mockReturnValueOnce(false).mockReturnValueOnce(true)
describe('test main function', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('expect to not throw', async () => {
await expect(mainFunction('/dummy/path/does/not/matter')).resolves
})
test('expect to throw', async () => {
await expect(mainFunction('/dummy/path/does/not/matter')).rejects.toBeInstanceOf(Error)
})
})