简体   繁体   English

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

[英]Cannot mock filesystem in nodejs unit tests

Overview概述

I have a simple module written in nodejs that uses fs-extra package to test if a file exists.我有一个用 nodejs 编写的简单模块,它使用fs-extra包来测试文件是否存在。 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 proceed 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:我想编写一个单元测试来测试以下逻辑:

  • If filepath exists, we expect to throw an error如果文件路径存在,我们希望抛出一个错误

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 .我不想弄乱真正的文件系统 - 以防我的代码包含一些可能会破坏它的讨厌的错误 - 所以我采用了另一种解决方案,使用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()
  })
})

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.发生这种情况是因为在 spec 文件中声明了mockfs fake-filesystem,因此主源文件中的fs模块不知道mockfs fake-filesystem 并检查真实文件系统。 By the time that I do not have a folder named /home/user/dummy in my real filesystem the check always fails.当我的真实文件系统中没有名为/home/user/dummy的文件夹时,检查总是失败。

Expected behaviour预期行为

mainFunction in spec file should throw规范文件中的mainFunction应该抛出

Actual behaviour实际行为

mainFunction in spec file DOES NOT throw规范文件中的mainFunction不会抛出

Other info其他信息

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 .我的测试服是Jest 22.3.0

After some search, I found the appropriate way to unit test the branch.经过一番搜索,我找到了对分支进行单元测试的合适方法。 We really do not have to use the mock-fs module.我们真的不必使用mock-fs模块。 We just have to mock pathExists method of fs-extra module to return one time the value false and one time the value true .我们只需要模拟fs-extra模块的pathExists方法以返回值false一次和值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)
  })
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM