Jest mocking默认导出- require vs import

zvms9eto  于 2023-04-27  发布在  Jest
关注(0)|答案(4)|浏览(170)

我在这里看到过关于嘲笑默认导出的问题,但我不认为这已经被问到了:
当模拟正在测试的模块的依赖项的默认导出时,如果模块使用ES6 import语句导入依赖项,则测试套件将无法运行,声明TypeError: (0 , _dependency.default) is not a function
在我的理解中,import module from location直接转换为const module = require(location).default,所以我非常困惑为什么会发生这种情况。我宁愿保持代码风格一致,而不是在原始模块中使用require调用。
有办法吗?
模拟测试文件:

import './modules.js';
import dependency from './dependency';

jest.mock('./dependency', () => {
   return {
      default: jest.fn()
   };
});

// This is what I would eventually like to call
it('calls the mocked function', () => {
   expect(dependency).toHaveBeenCalled();
});

Dependency.js

export default () => console.log('do something');

module.js(不工作)

import dependency from './dependency.js';
dependency();

module.js(工作)

const dependency = require('./dependency.js').default;
dependency();
qgzx9mmu

qgzx9mmu1#

您可以使用es6 importrequire js在jest测试中导入js文件。
在使用es6 import时,你应该知道jest正在尝试解析所有的依赖项,并且还会调用你要导入的类的构造函数。在这一步中,你不能mock它。依赖项必须成功解析,然后你才能继续进行mock。
我还应该补充一点,正如在这里可以看到的,jest默认情况下将所有jest.mocks提升到文件的顶部,因此放置导入的顺序并不重要。
但是你的问题是不同的,你的mock函数假设你已经使用require js包含了js文件。

jest.mock('./dependecy', () => {
   return {
      default: jest.fn()
   };
});

使用require js导入文件时,它的结构如下:

因此,假设我已经使用require js导入了名为“Test”的类,并且它有一个名为“doSomething”的方法,我可以在测试中通过执行以下操作来调用它:

const test = require('../Test');
test.default.doSomething();

当使用es6 import导入它时,您应该以不同的方式进行。使用相同的示例:

import Test from '../Test';
Test.doSomething();

编辑:如果你想使用es6 import,请将mock函数改为:

jest.mock('./dependecy', () => jest.fn());
o7jaxewo

o7jaxewo2#

如果您想使用import dependency from 'dependency',请参阅ES模块简短答案

jest.mock('dependency', () => ({
  ...jest.requireActual('dependency'),
  __esModule: true,
  default: jest.fn(),
}))
nlejzf6q

nlejzf6q3#

你试过这样的东西吗?我一直在处理默认导出模拟几个月,直到我发现了这个。

jest.mock('./dependency', () => () => jest.fn());

这行代码背后的想法是,您导出的模块是一个函数。因此,您需要让Jest知道它必须将所有./dependency文件模拟为一个函数,该函数返回jest.fn()

d6kp6zgx

d6kp6zgx4#

我不得不这样做在vue和jest:
尽管在代码中我使用了默认的导入,但在单元测试中我必须这样命名导入:

import * as someName from 'dependency';

然后我使用奇怪的属性'__esModule'来允许jest像这样使用默认构造函数:

jest.mock('dependency', () => ({
  __esModule: true,
  default: jest.fn(),
}));

最后,在我的单元测试中,我使用了带有实现的spy on default constructor:

const mySpy = jest.spyOn(someName, 'default').mockImplementation(params => {
 params.doSomeThing();
});
...
expect(mySpy).toBeCalledWith({...})

成功了,也是唯一成功的方法

相关问题