【发布时间】:2018-08-07 01:57:14
【问题描述】:
概述
我有一个用 nodejs 编写的简单模块,它使用 fs-extra 包来测试文件是否存在。当路径存在时模块抛出,否则继续下一个过程。这是源文件:
// - main.js -
import fs from 'fs-extra'
export default async (pathName) => {
// Do not proceed if path already exists.
if (await fs.pathExists(projectPath)) {
throw new Error(chalk.red.bold(`${projectPath} already exists`))
}
// more logic here
}
我想写一个单元测试来测试下面的逻辑:
- 如果文件路径存在,我们预计会抛出错误
我不想弄乱真正的文件系统——以防我的代码包含一些可能破坏它的讨厌的错误——所以我采用了另一种解决方案,使用mock-fs 模拟文件系统。这是规范文件:
// - 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 fake-filesystem,因此主源文件中的fs 模块不知道mockfs fake-filesystem 并检查真实的。当我的真实文件系统中没有名为 /home/user/dummy 的文件夹时,检查总是失败。
预期行为
spec 文件中的mainFunction 应该抛出
实际行为
spec 文件中的mainFunction 不会抛出
其他信息
我想我可以把这个单元测试变成一个集成测试。但我不想。有什么解决办法吗?我必须使用其他软件包吗? 我的测试服是Jest 22.3.0。
【问题讨论】:
-
你为什么不测试一些保证不存在的随机路径?喜欢
/does/not/exist。我很确定这不会破坏您的文件系统,因为您依赖于fs-extra模块,所以只要该模块不破坏文件系统,您就可以使用了。 -
@devius 感谢您的回复。这样做的意思是找到一种方法来通过单元测试而不是 e2e 来做到这一点。我知道您的回答是一个不错的选择,但我想知道是否有其他方法可以做到这一点。
-
嗯....它非常复杂,但是您可以修改
requires缓存中的fs-extra模块以指向您的mock-fs模块,然后在测试完成后重新加载正确的fs-extra模块。但这似乎太麻烦了,因为害怕损坏文件系统,或者试图将“单元”测试非常严格。也许我应该添加这个作为答案。 -
@devius 感谢您的 cmets。我找到了解决方案。见下文。
标签: node.js unit-testing mocking fs