如何重置测试之间导入的模块

Ami*_*ico 3 javascript jest es6-modules

假设我有一个模块,需要在应用程序启动时初始化一次(以传递配置)。模块将如下所示:

MyModule.js

let isInitiazlied;

const myModule = {

    init: function() {
        isInitiazlied = true;
    },
    do: function() {
        if (!isInitiazlied)
            throw "error"
        //DO THINGS
    }
}

export default myModule;
Run Code Online (Sandbox Code Playgroud)

我想用玩笑来对它进行单元测试。测试文件看起来像这样:

MyModule.test.js

import myModule from './MyModule'

describe('MyModule', () => {
    describe('init', () => {
        it('not throws exception when called', () => {
            expect(() => myModule.init()).not.toThrow();
        });
    })
    describe('do', () => {
        it('throw when not init', () => {
            expect(() => myModule.do()).toThrow();
        });
    })
})
Run Code Online (Sandbox Code Playgroud)

当我运行测试时,第二次测试失败,因为模块已经初始化,因此不会引发异常。我试过在beforeEach中使用jest.resetModules(),但这没有用。

有没有解决的方法(不同的模块模式/测试用例)?

lta*_*ajs 11

您必须重新导入或重新需要您的模块。查看文档或此问题以获取更多信息:

https://github.com/facebook/jest/issues/3236

https://facebook.github.io/jest/docs/en/jest-object.html#jestresetmodules

describe('MyModule', () => {
    beforeEach(() => {
        jest.resetModules()
    });

    describe('init', () => {
        const myModule = require('./MyModule');

        it('not throws exception when called', () => {
            expect(() => myModule.init()).not.toThrow();
        });
    })
    describe('do', () => {
        const myModule = require('./MyModule');

        it('throw when not init', () => {
            expect(() => myModule.do()).toThrow();
        });
    })
})
Run Code Online (Sandbox Code Playgroud)

  • 有效!谢谢。唯一缺少的是将 **.default** 添加到 require 语句中,因为 MyModule 导出为默认值 (2认同)

Luc*_*cio 7

@ltamajs 解决方案非常适合require但在您使用的情况下,import您将收到下一个错误。

SyntaxError: /path/to/test/file.js: 'import' and 'export' may only appear at the top level
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您可以使用babel-plugin-dynamic-import-node插件,然后重置模块。总的来说,它看起来像这样:

describe('MyTests', () => {
  let MyModule;

  beforeEach(() => {
    return import('../module/path').then(module => {
      MyModule = module;
      jest.resetModules();
    });
  });

  test('should test my module', () => {
    expect(MyModule.aMethod).not.toBeUndefined();
  });
});
Run Code Online (Sandbox Code Playgroud)

来源:https : //github.com/facebook/jest/issues/3236#issuecomment-698271251

  • 如果您将其写为“let MyModule: typeof import('../module/path')”,您甚至可以保留“MyModule”类型 (7认同)
  • 即使没有 babel 插件,这对我来说也很有效,谢谢! (3认同)
  • @MichaelSherrisCaley“`beforeEach` ...可以通过返回承诺来处理异步代码” - 请参阅https://jestjs.io/docs/setup-teardown#repeating-setup-for-many-tests (2认同)