Cannot mock filesystem in nodejs unit tests

会有一股神秘感。 提交于 2019-12-11 13:47:31

问题


Overview

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:

  • 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. 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. By the time that I do not have a folder named /home/user/dummy in my real filesystem the check always fails.

Expected behaviour

mainFunction in spec file should throw

Actual behaviour

mainFunction in spec file DOES NOT throw

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.


回答1:


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


来源:https://stackoverflow.com/questions/49008358/cannot-mock-filesystem-in-nodejs-unit-tests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!