Jest:当同一个module也有命名导出时,如何模拟默认导出组件?

IT技术 javascript reactjs unit-testing jestjs es6-modules
2021-05-07 13:33:30

我有一个 ES6 module,它默认导出一个 React Component 类,但也导出一个普通的 JS 函数作为命名导出。在测试使用此module的其他包时,我想模拟默认导出的组件和命名的导出函数,以保持我的单元测试纯净。

该module看起来像这样:

import React, { Component } from 'react';

export default class MyComponent extends Component {
  render() {
    return <div>Hello</div>
  }
}

export function myUtilityFunction() { return 'foo' };

我想使用以下语法来模拟导出:

import React from 'react';
import MyComponent, { myUtilityFunction } from './module';

jest.mock('./module');
MyComponent.mockImplementation(() => 'MockComponent');
myUtilityFunction.mockImplementation(() => 'foo');

但是,当我尝试使用此语法时,MyComponent 在其他组件中使用时似乎不会被模拟。当我尝试像这样模拟 MyComponent 并自行呈现它时,它呈现为 null。

这种行为很奇怪,因为如果我使用完全相同的语法,但两个导入都是 JavaScript 函数,模拟会按预期工作。请参阅我在此处打开的 StackOverflow 问题,该问题确认当导入是两个函数时语法有效。

这是演示该问题的 GitHub 存储库,以及我尝试过的几种解决方案:https : //github.com/zpalexander/jest-enzyme-problem

您可以构建 repo 并使用 yarn install && yarn test 运行测试

谢谢!

2个回答

另一个解决方案对我不起作用。这就是我所做的:

  jest.mock('./module', () => ({
    __esModule: true,
    myUtilityFunction: 'myUtilityFunction',
    default: 'MyComponent'
  }));

另一种方法:

jest.unmock('../src/dependency');

const myModule = require('../src/dependency');
myModule.utilityFunction = 'your mock'

我认为问题在于 ShallowWrapper 类的 getElement 方法需要传递一个包含渲染方法的类。为此,您的 MyComponent.mockImplementation 需要更全面地模拟类构造函数。

有关如何模拟类构造函数的详细信息,请参阅从“mockImplementation 也可用于模拟类构造函数”开始的 Jest 文档:https ://facebook.github.io/jest/docs/en/mock-function-api 。 html#mockfnmockimplementationfn

使用 Jest 文档作为模型,我们可以模拟 MyComponent 类构造函数使其可以像这样被酶浅渲染:

MyComponent.mockImplementation(() => {
  return {
    render: () => <div>MockComponent</div>
  };
});

现在,当 getElement 去寻找渲染方法时,它会找到它。

这是在您的存储库中的 App.mockImplementation.test.js 文件上实现此更改的要点:https ://gist.github.com/timothyjellison/a9c9c2fdfb0b30aab5698dd92e901b24