使用 Jest 通过 props 模拟 React 组件

问题描述 投票:0回答:7

我有一个 React 组件,其中包含一些其他组件,这些组件依赖于对 Redux 存储等的访问,这在进行完整的 Enzyme 挂载时会导致问题。让我们说一个这样的结构:

import ComponentToMock from './ComponentToMock';

<ComponentToTest>
  ...some stuff
  <ComponentToMock testProp="This throws a warning" />
</ComponentToTest>

我想使用Jest的

.mock()
方法来模拟子组件,这样就不会成为测试的问题了。

我知道我可以用类似的东西模拟一个直接组件:

jest.mock('./ComponentToMock', () => 'ComponentToMock');

但是,由于该组件通常会接收 props,React 会感到不安,并发出有关未知 props(在本例中为

testProp
)传递给
<ComponentToMock />
的警告。

我尝试返回一个函数,但是你不能在 Jest 模拟中返回 JSX(据我所知),因为它被提升了。在这种情况下它会抛出错误。

所以我的问题是我怎样才能

a) 获取

ComponentToMock
忽略传递给它的 props,或者

b)返回一个 React 组件,可用于模拟我不担心测试的子组件。

或者...有更好的方法吗?

reactjs unit-testing mocking jestjs enzyme
7个回答
49
投票

文档底部有一个关于

jest.mock()
的注释,用于防止提升行为:

注意:使用

babel-jest
时,对
mock
的调用将自动被 提升到代码块的顶部。如果您愿意,请使用
doMock
明确避免这种行为。

然后您可以按照您的描述进行操作:返回一个函数,该函数是您不需要测试的组件的存根。

jest.doMock('./ComponentToMock', () => {
  const ComponentToMock = () => <div />;
  return ComponentToMock;
});

const ComponentToTest = require('./ComponentToTest').default;

为存根组件命名很有帮助,因为它是在快照中渲染的。


28
投票

自从我问这个问题以来,我学到了更多东西。这是处理需要传递 props 的模拟组件的另一种(更好?)方法:使用模块 mock 文件

首先在组件文件夹下的

__mocks__
文件夹中创建一个与要模拟的组件同名的文件,例如

.
|- /ComponentToMock.js
└- /__mocks__/ComponentToMock.js <-- create this folder/file!

注意:在撰写本文时,文件夹必须称为

__mocks__
(您需要在需要模拟组件的每个文件夹中创建
__mocks__
。如果下划线让您不高兴,只需假装他们不在那里;) )

接下来,在这个模拟文件中,您可以根据需要编写文件,例如

// This code would live in ./__mocks__/ComponentToMock.js
import React from 'react';
const ComponentToMock = ({ testProp }) => <div>A mock with '{testProp}' passed!</div>;
export default ComponentToMock;

然后在测试文件中,将Jest模拟语句更改为:

jest.mock('./ComponentToMock');

当 Jest 遇到不带第二个函数参数的

.mock()
时,它会自动查找
__mocks__
文件夹。然而,即使模拟语句在被测试的组件中被提升,这也不会影响模拟本身的导入 - 这就是为什么它能够导入和编译 React 组件!

这似乎对于需要传递 props 的模拟组件效果很好,否则如果返回 null 函数,则会产生 prop 警告(但如果组件没有接收 props,则继续使用是完全可以接受的)。我希望这可以帮助一些人。


4
投票

除了接受的答案之外,如果您使用多个导出,则可以按如下方式进行模拟:

// Component.jsx

export { A, B };
// Component-test.js

jest.mock("../src/Component", () => {
  return {
    A: true,
    B: () => {
      return <></>;
    },
  };
})

参考博客:https://thoughtbot.com/blog/mocking-react-components-with-jest


0
投票

就我而言,我无法使模拟工作。

结果是区分大小写的问题:

模块文件名:

Autosuggest.js

我是如何嘲笑它的:

jest.mock('./AutoSuggest', ...); 
<-- wrong cases


0
投票

Jest 推荐,对于我来说非常适合默认导出组件

https://jestjs.io/docs/next/tutorial-react

jest.mock('../SomeDirectory/SomeComponent', () => 'SomeComponent');


0
投票

如果有人使用

Vitest
尝试这个

vi.mock('path-to-component', () => {
  return {
    default: () => <div />, // your mock React component
  };
});

-1
投票
const mockComponent = ComponentName => ({ children, ...props }) => (
  <ComponentName {...{ '[mockComponent]': true }} {...props}>
    {children}
  </ComponentName>
);

export default mockComponent;
jest.mock('../ComponentToMock', () => {
  const mockComponent = require('./mockComponent').default;

  return mockComponent('ComponentToMock');
});
© www.soinside.com 2019 - 2024. All rights reserved.