用Jest测试module.hot

时间:2017-07-11 14:13:12

标签: javascript reactjs jestjs

我试图通过热模块重新加载设置将覆盖率提高到100%。

在我的模块中,我有这个:

// app.js
if (module && module.hot) module.hot.accept();

在测试文件中,我正在尝试这样做

// app.test.js
it('should only call module.hot.accept() if hot is defined', () => {
    const accept = jest.fn();
    global.module = { hot: { accept } };
    jest.resetModules();
    require('./app');
    expect(accept).toHaveBeenCalled();
  }
);

但是当我在app.js中注销模块时,它会显示需要的东西,但不包含测试设置的热方法。

2 个答案:

答案 0 :(得分:0)

如果您有引用模块对象的变量,则可以将模拟模块对象注入该变量中以进行测试。例如,您可以执行以下操作:

// app.js

// ...
  moduleHotAccept(module);
// ...

export function moduleHotAccept(mod) {
  if (mod && mod.hot) {
    mod.hot.accept();
  }
}

可以像这样测试:

// app.test.js
import { moduleHotAccept } from './app'

it('should only call hot.accept() if hot is defined', () => {
    const accept = jest.fn();
    const mockModule = { hot: { accept } };
    moduleHotAccept(mockModule);
    expect(accept).toHaveBeenCalled();
  }
);

it('should not throw if module is undefined', () => {
    expect(moduleHotAccept).not.toThrow();
  }
);

it('should not throw if module.hot is undefined', () => {
    expect(
      () => moduleHotAccept({notHot: -273})
    ).not.toThrow();
  }
);

答案 1 :(得分:0)

我也需要它,而无法从外部传递它。

我的解决方案是使用一个开玩笑的"transform",允许我稍微修改使用module.hot的文件的代码。

因此,要进行设置,您需要添加:

// package.json

"transform": {
  "file-to-transform.js": "<rootDir>/preprocessor.js"
//-------^ can be .* to catch all
//------------------------------------^ this is a path to the transformer
},

preprocessor.js内部,

// preprocessor.js

module.exports = {
  process(src, path) {
    if( path.includes(... the path of the file that uses module.hot)) {
      return src.replace('module.hot', 'global.module.hot');
    }

    return src;
  },
};

该变压器会将module.hot替换为global.module.hot,这意味着您可以在测试中控制它的值,如下所示:

// some-test.spec.js

global.module = {
  hot: {
    accept: jest.fn,
  },
};

希望有帮助。