【问题标题】:How do I mock ES modules in NodeJS?如何在 NodeJS 中模拟 ES 模块?
【发布时间】:2018-12-05 11:33:10
【问题描述】:

假设我已经实现了一个模块如下:

import { foo } from 'dep1'

export const bar = () => foo()

我将如何模拟 dep1 以便我可以对 bar 进行单元测试?

【问题讨论】:

    标签: javascript node.js ecmascript-6 node-modules


    【解决方案1】:

    一种可能的方法是使用 ES 模块加载器挂钩。

    假设dep1 包含工作代码,我们想模拟它。我将创建一个名为 mymodule.mocks.mjs 的文件,我将在其中模拟 foo

    // Regular mymodule.mjs
    import { foo } from 'dep1'
    
    export const bar = () => foo()
    

    // Mocked mymodule.mocks.mjs
    
    // dep1.foo() returns string
    export const bar = () => 'whatever'
    

    现在我们应该能够在测试运行期间请求mymodule.mjs 时加载mymodule.mocks.mjs

    所以我们实现testModuleLoader.mjs

    这是一个实现*.mocks.mjs 约定的自定义模块加载器挂钩:

    import { existsSync } from 'fs'
    import { dirname, extname, basename, join } from 'path'
    import { parse } from 'url'
    
    // The 'specifier' is the name or path that we provide
    // when we import a module (i.e. import { x } from '[[specifier]]')
    export function resolve (
       specifier,
       parentModuleURL,
       defaultResolver
    ) {
       // For built-ins
       if ( !parentModuleURL )
          return defaultResolver ( specifier, parentModuleURL )
    
       // If the specifier has no extension we provide the
       // Michael Jackson extension as the default one
       const moduleExt = extname ( specifier ) || '.mjs'
       const moduleDir = dirname ( specifier )
       const { pathname: parentModulePath } = parse (
          parentModuleURL
       )
       const fileName = basename ( specifier, moduleExt )
    
       // We build the possible mocks' module file path
       const mockFilePath = join (
          dirname ( parentModulePath ),
          moduleDir,
          `${fileName}.mocks${moduleExt}`
       )
    
       // If there's a file which ends with '.mocks.mjs'
       // we resolve that module instead of the regular one
       if ( existsSync ( mockFilePath ) )
          return defaultResolver ( mockFilePath, parentModuleURL )
    
       return defaultResolver ( specifier, parentModuleURL )
    }
    

    使用它

    只是将其提供给node

    node --experimental-modules --loader ./path/to/testModuleLoader.mjs ./path/to/app.mjs
    

    Learn more 关于 ES 模块加载器钩子。

    【讨论】:

      猜你喜欢
      • 2023-02-14
      • 1970-01-01
      • 2016-01-13
      • 2021-04-04
      • 1970-01-01
      • 2022-10-05
      • 2021-04-18
      • 2017-05-09
      • 2013-11-25
      相关资源
      最近更新 更多