How can I mock Webpack's require.context in Jest?

匿名 (未验证) 提交于 2019-12-03 02:56:01

问题:

Suppose I have the following module:

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

Jest complains because it doesn't know about require.context:

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

How can I mock it? I tried using setupTestFrameworkScriptFile Jest configuration but the tests can't see any changes that I've made in require.

回答1:

Extract the call to a separate module:

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

Use the new module in the module where you extracted it from:

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

Create a mock for the newly created bundle-loader module:

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

Use the mock in your test:

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


回答2:

I had the same problem, then I made a 'solution'.

I'm pretty sure that this is not the best choice. I ended up stopping using it, by the points answered here:

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

But if really need it, you should include the polyfill below in every file that you call it (not on the tests itself, because the require will be no global overridden in a Node environment).

// 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;   }; } 

With this function, you don't need to change any require.context call, it will execute with the same behavior (if it's on webpack, using the original, and if in Jest, with the mocked function).



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