2016-07-12 162 views
15

假设我有以下模块:如何在Jest中模拟Webpack的require.context?

var modulesReq = require.context('.', false, /\.js$/); 
modulesReq.keys().forEach(function(module) { 
    modulesReq(module); 
}); 

玩笑抱怨,因为它不知道require.context

FAIL /foo/bar.spec.js (0s) 
● Runtime Error 
    - TypeError: require.context is not a function 

我怎么能嘲笑呢?我尝试使用setupTestFrameworkScriptFile Jest配置,但测试无法看到我在require中所做的任何更改。

+0

您是否找到答案? – BigDong

回答

4

我有同样的问题,然后我提出'解决方案'。

我很确定这不是最好的选择。我结束了回采使用,但是在这里回答要点:

https://github.com/facebookincubator/create-react-app/issues/517 https://github.com/facebook/jest/issues/2298

但如果真的需要它,你应该包括下面的填充工具在每次你怎么称呼它(而不是在测试本身的文件,因为在节点环境中require将不会被全局覆盖)。

// This condition actually should detect if it's an Node environment 
if (typeof require.context === 'undefined') { 
    const fs = require('fs'); 
    const path = require('path'); 

    require.context = (base = '.', scanSubDirectories = false, regularExpression = /\.js$/) => { 
    const files = {}; 

    function readDirectory(directory) { 
     fs.readdirSync(directory).forEach((file) => { 
     const fullPath = path.resolve(directory, file); 

     if (fs.statSync(fullPath).isDirectory()) { 
      if (scanSubDirectories) readDirectory(fullPath); 

      return; 
     } 

     if (!regularExpression.test(fullPath)) return; 

     files[fullPath] = true; 
     }); 
    } 

    readDirectory(path.resolve(__dirname, base)); 

    function Module(file) { 
     return require(file); 
    } 

    Module.keys =() => Object.keys(files); 

    return Module; 
    }; 
} 

使用此功能,您无需更改任何require.context调用,它将与相同的行为执行(如果是的WebPack,使用原来的,如果是开玩笑,用嘲笑的功能)。

5

提取呼叫到一个单独的模块:

// src/js/lib/bundle-loader.js 
/* istanbul ignore next */ 
module.exports = require.context('bundle-loader?lazy!../components/', false, /.*\.vue$/) 

在模块中使用新的模块,你从中提取它:

// src/js/lib/loader.js 
const loadModule = require('lib/bundle-loader') 
// ... 

创建新创建的束装载机模块模拟:

// test/unit/specs/__mocks__/lib/bundle-loader.js 
export default() =>() => 'foobar' 

使用模拟测试中的:

// test/unit/specs/lib/loader.spec.js 
jest.mock('lib/bundle-loader') 
import Loader from 'lib/loader' 

describe('lib/loader',() => { 
    describe('Loader',() => { 
    it('should load',() => { 
     const loader = new Loader('[data-module]') 
     expect(loader).toBeInstanceOf(Loader) 
    }) 
    }) 
}) 
+0

非常好。但是如果我实际上需要包含原始模块?我想唯一的解决办法就是在答案中使用我的实现(这也不完美)。国际海事组织,我仍然认为最好的选择是停止使用它。 –