首页 文章

无法在nodejs单元测试中模拟文件系统

提问于
浏览
1

概述

我有一个用nodejs编写的简单模块,它使用 fs-extra 包来测试文件是否存在 . 模块在路径存在时抛出,否则进入下一个过程 . 这是源文件:

// - 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
}

我想写一个测试波纹管逻辑的单元测试:

  • 如果存在filepath,我们希望抛出错误

我不想搞砸真正的文件系统 - 如果我的代码包含一些可能会破坏它的讨厌的bug - 所以我去了另一个解决方案,使用 mock-fs 模拟文件系统 . 这是spec文件:

// - 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()
  })
})

有什么问题?

每次运行测试时,主函数都不会抛出 . 发生这种情况是因为在spec文件中声明了 mockfs 伪文件系统,因此主源文件中的 fs 模块不知道 mockfs 伪文件系统并检查真实文件系统 . 当我在我的真实文件系统中没有名为 /home/user/dummy 的文件夹时,检查总是失败 .

预期的行为

应该抛出spec文件中的 mainFunction

实际行为

在spec文件中 mainFunction 不要抛出

其他信息

我想我可以把这个单元测试变成集成测试 . 但我不想 . 这有什么问题吗?我必须使用其他套餐吗?我的测试套装是 Jest 22.3.0 .

1 回答

  • 1

    经过一番搜索,我找到了对分支进行单元测试的合适方法 . 我们真的不必使用 mock-fs 模块 . 我们只需要模拟 fs-extra 模块的 pathExists 方法,一次返回值 false ,一次返回值 true . 贝娄,我发布了我的spec文件的工作版本:

    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)
      })
    })
    

相关问题