首页 > 解决方案 > 模拟类是从带有 jest 的包中导入的对象的属性

问题描述

我有以下情况:

.js 代码大致如下所示:

import foo from 'foo/dist/foo.min';
const { Bar, Baz } = foo;
...
const fooBar = new Bar();

在我的 .test.js 文件中,我现在像这样模拟包:

jest.mock('foo/dist/foo.min');

自动模拟按预期工作,但当然不允许我监视 Bar 和 Baz 的构造函数,这正是我想要的。

我试图在我的 .test.js 文件中简单地做到这一点:

import foo from 'foo/dist/foo.min';
jest.mock('foo/dist/foo.min');
foo.Bar = jest.fn();
foo.Baz = jest.fn();

但这似乎没有任何作用,我的假 jest.fn() 构造函数永远不会被调用。

我已在文档中阅读此页面:https ://jestjs.io/docs/en/es6-class-mocks.html但似乎假设要模拟的 ES6 类是直接从模块中导出的,并且是在项目内部而不是 npm 包中。

自动模拟对我不起作用,因为类本身不会导出。

我将不胜感激有关如何解决此问题的任何建议。

标签: javascriptunit-testingmockingjestjs

解决方案


几点注意事项:

  • babel-jest提升呼叫,jest.mock以便他们首先发生。
  • 创建的自动模拟Jest反映了模块的结构。

因此调用jest.mock('foo/dist/foo.min');意味着Jest将为该测试期间运行的任何代码自动模拟该模块,并且自动模拟将反映原始模块的结构。


看起来您的代码一运行就Bar调用构造函数。

这意味着以下测试应该有效:

import foo from 'foo/dist/foo.min';  // foo is already auto-mocked...
import './code';  // import your code (which calls the Bar constructor)

jest.mock('foo/dist/foo.min');  // ...because this runs first

test('constructor was called', () => {
  expect(foo.Bar).toHaveBeenCalled();  // SUCCESS
})

看起来您的测试不起作用,因为您在代码运行foo.Bar = jest.fn(); 设置(覆盖在您的代码运行时确实被调用的较早spy版本


推荐阅读