【问题标题】:Mocking and testing require.resolve calls in jest开玩笑地模拟和测试 require.resolve 调用
【发布时间】:2018-06-03 02:20:23
【问题描述】:

我想在 jest 测试套件中模拟节点的内置函数 require.resolve。这是一个问题on repl.it 和代码本身的工作示例:

测试对象(例如):

const requirer = () => {
  try {
    return require.resolve('./add')
  } catch (error) {
    console.error('failed to find a module')
  }
}

module.exports = requirer

测试套件:

const requirer = require('./requirer')

describe('attempt to mock require.resolve', () => {
   it('does not work', () => {
     require.resolve = jest.fn(arg => `./${arg}`)
     console.log(
       'is require.resolve mocked',
       jest.isMockFunction(require.resolve)) // will say true

     requirer()

     expect(require.resolve).toHaveBeenCalledTimes(1)
     expect(require.resolve).toBeCalledWith('')
  })
})

在测试套件声明中一切正常(参见jest.isMockFunction(require.resolve) 的输出)并且模拟工作。但是对于测试对象require.resolve 仍然具有原始功能。

由于这个问题,这不是纯粹的单元测试。

例如,如果我模拟 process.exit 一切都按预期工作。

【问题讨论】:

    标签: node.js unit-testing jestjs mocking


    【解决方案1】:

    我知道这不是您正在寻找的,但这是我能够“模拟”require.resolve 的解决方法。 jest 中有一个有趣的功能允许您定义自己的模块解析器: https://jestjs.io/docs/en/configuration#resolver-string

    考虑到这一点,这基本上就是我所做的:

    • 我创建了自己的解析器,如下所示:
    const glob = require('glob');
    
    let mapping = {};
    
    // Looks for "module-resolution.json" files in all the `__tests__` directories
    glob
      .sync(`${__dirname}/../../packages/**/src/**/__tests__/modules-resolution.json`)
      .forEach((file) => {
        // For each of them, merges them in the "mapping" object
        mapping = { ...mapping, ...require(file) };
      });
    
    function resolver(path, options) {
      // If the path corresponds to a key in the mapping object, returns the fakely resolved path
      // otherwise it calls the Jest's default resolver
      return mapping[path] || options.defaultResolver(path, options);
    }
    
    module.exports = resolver;
    
    • 然后,我在我的 jest 配置文件中进行了配置:
    module.exports = {
      roots: ['<rootDir>'],
      testMatch: ['<rootDir>/packages/**/__tests__/**/*.test.js'],
      collectCoverageFrom: ['packages/**/src/**/*.js', '!packages/**/src/__tests__/**'],
      resolver: '<rootDir>/test-utils/resolver',
    };
    
    • 最后,我可以在我的测试文件夹中创建modules-resolution.json 文件,如下所示:
    {
      "fake-module": "/path/to/fake-module"
    }
    

    到目前为止,这为我完成了这项工作,我认为,从这个示例开始,我们可以做一些更复杂但对开发人员更友好的事情! 当然,如果这个功能可以直接包含在 jest 中就更好了! 无论如何,我希望这会对你们中的一些人有所帮助?

    【讨论】:

      【解决方案2】:

      所以,这不是一个完美的解决方案,但注入 (DI) require.resolve 更简单

      const requirer = (resolver) => {
        try {
          return resolver('./add')
        } catch (error) {
          console.error('failed to find a module')
        }
      }
      
      module.exports = requirer
      

      现在在测试套件中传递 require.resolve 的模拟版本可以按预期工作

      const requirer = require('./requirer')

      describe('attempt to mock require.resolve', () => {
         it('works', () => {
           require.resolve = jest.fn(arg => `./${arg}`)
           console.log(
             'is require.resolve mocked',
             jest.isMockFunction(require.resolve)) // will say true
      
           requirer(require.resolve)
      
           expect(require.resolve).toHaveBeenCalledTimes(1)
           // expect(require.resolve).toBeCalledWith('')
        })
      })
      

      【讨论】:

        猜你喜欢
        • 2021-06-16
        • 1970-01-01
        • 2017-11-19
        • 2017-07-01
        • 1970-01-01
        • 2021-02-07
        • 2023-03-08
        • 2020-03-05
        • 1970-01-01
        相关资源
        最近更新 更多