使用 Jest 和 React 模拟非默认函数

IT技术 javascript reactjs unit-testing webpack jestjs
2021-05-03 17:01:36

在测试文件中,我需要渲染一个组件,同时模拟它的一些子组件。文件结构看起来像这样。

文件 1

import {A, B} from 'a-module';

export function MyComponent() {
    return (
        <div>
            <A /> // I need to mock
            <B /> // these components out
        </div>
    );
}

档案 2

import {MyComponent} from 'File 1';

/*
 * In this file I would like to render MyComponent but
 * have components A and B be replaced by mocks
 */

我试过这样做,jest.mock('a-module', () => 'Blah');但这并没有成功地模拟组件。但是,这在文件 1 中使用默认导入时有效。

在模拟组件A在文件 2 中B渲染时的任何帮助MyComponent将不胜感激!

3个回答

您可以像这样模拟非默认值:

jest.mock('a-module', () => ({
  __esModule: true,
  default: () => 'Blah',
  A: () => 'Blah',
  B: () => 'Blah'
}));

https://remarkablemark.org/blog/2018/06/28/jest-mock-default-named-export/

或使用 __mocks__

作为替代方案,您可以__mocks__在原始module旁边的文件夹下创建一个与module同名的文件

a_module_folder > 
    a-module.js
    __mocks__ >
        a-module.js

并且该模拟应该只导出模拟版本:

export const A = () => 'Blah';
export const B = () => 'Blah';

然后像这样模拟:

jest.mock('a-module');

对于 node_modules 只需将__mocks__文件夹放在与node_modules

https://jestjs.io/docs/en/manual-mocks

测试 React 组件主要是用 Enzyme 完成的,如果你只尝试用 Jest 来完成,那么你可能选择了错误的工具。我只能猜测为什么你需要模拟一个组件,但你肯定可以用 Enzyme 来实现它。

专门为测试 React 而创建的Enzyme 浅层渲染Jest 本身不能渲染组件。根据Airbnb 文档的定义是:

浅渲染有助于限制您将组件作为一个单元进行测试,并确保您的测试不会间接断言子组件的行为。

简单地说,它将渲染测试组件 1 级深,例如

// File2.js

import { MyComponent } from 'File1';
import { shallow } from 'enzyme';

describe('MyComponent', () => {
  it('should render shallowly my component', () => {
    const wrapper = shallow(<MyComponent />);
    console.log(wrapper.debug()); 
    // output:
    //   <div>
    //     <A />
    //     <B />
    //   </div>
    // Note: even if component <A /> is consisting of some markup, 
    // it won't be rendered 
  });
});

基本上你不需要模拟它的任何依赖组件,这些已经用酶模拟了 shallow()

相反,您可以做的是测试何时将某些props传递给<MyComponent />依赖组件<A /><B />接收预期的props。

const wrapper = shallow(<MyComponent foo={1} bar={2} />);
expect(wrapper.find('A').props().foo).toEqual(1);
expect(wrapper.find('B').props().bar).toEqual(2);

如果您有一个不是默认导出的 react 组件,这实际上是一个很好的做法(因为应该避免默认导出)

export function MyComponentX() {
    return (
        <div>...</div>
    );
}

您可以轻松地开玩笑地嘲笑它:

jest.mock('path/to/MyComponentX', () => ({
  MyComponentX: () => <>MOCK_MY_COMPONENT_X</>,
}));