开玩笑的单次导入模拟模块

时间:2018-10-27 16:42:10

标签: javascript unit-testing ecmascript-6 mocking jestjs

jest与ES6模块和babel-jest一起使用时,所有jest.mock的调用都是hoisted
假设我想为测试的类模拟fs模块,但保留其余模块的原始实现(例如,在测试期间使用的一些utils)。
考虑以下示例:

class UnderTest {
  someFunction(){
    fs.existsSync('blah');
  }
}

class TestUtility {
  someOtherFunction(){
    fs.existsSync('blahblah');
  }
}

测试:

it('Should test someFunction with mocked fs while using TestUtility'', () => {
  testUtility.someOtherFunction(); // Should work as expected
  underTest.someFunction(); // Should work with mock implementation of 'fs' 
})

现在,人们希望通过以下方法为fs而不是UnderTest来模拟TestUtility模块。

import {TestUtility} from './test-utility';

jest.mock('fs');

import {UnderTest } from './under-test';

但是,由于吊装,fs模块将针对所有模块进行模拟(这是不可取的)。

有什么办法可以实现所描述的行为?

2 个答案:

答案 0 :(得分:2)

要选择在测试jest.doMock(moduleName, factory, options)jest.dontMock(moduleName)中模拟模块,请选择退出。

jest.doMock(模块名称,工厂,选项)

  

使用babel-jest时,对mock的调用将自动提升到代码块的顶部。如果要明确避免这种行为,请使用此方法。

jest.dontMock(moduleName)

  

使用babel-jest时,对unmock的调用将自动提升到代码块的顶部。如果要明确避免这种行为,请使用此方法。

所以在您的情况下,我会尝试类似的方法

beforeEach(() => {
  jest.resetModules();
});

it('Should test someFunction with mocked fs while using TestUtility'', () => {
  jest.dontMock('fs');
  testUtility.someOtherFunction(); // Should work as expected
  jest.doMock('fs', () => {
    return ... // return your fs mock implementation;
  });
  underTest.someFunction(); // Should work with mock implementation of 'fs' 
})

答案 1 :(得分:0)

您可能应该使用玩笑的requireActual

const fs = jest.requireActual('fs'); // Unmockable version of jest 

class TestUtility {
  someOtherFunction(){
    fs.existsSync('blahblah');
  }
}

来自documentation

  

Jest允许您在测试中模拟整个模块,这对于测试代码是否正确地从该模块调用函数很有用。但是,有时您可能想在测试文件中使用模拟模块的某些部分,在这种情况下,您要访问原始实现,而不是模拟版本。