首页 > 解决方案 > 用于单一导入的 Jest 模拟模块

问题描述

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

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模块将被所有模块模拟(这是不希望的)。

有没有办法实现所描述的行为?

标签: javascriptunit-testingecmascript-6mockingjestjs

解决方案


在测试中选择退出模拟模块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' 
})

推荐阅读