【问题标题】:How to replace a React component with a mock when testing with Jest使用 Jest 进行测试时如何用模拟替换 React 组件
【发布时间】:2020-10-08 19:56:13
【问题描述】:

在我正在从事的项目中,我真的被困在这个问题上,我发现的所有答案似乎都很简单,但它们对我没有用。可能我不太了解什么是 mock,我真的可以参考一些指导。

我正在测试一个父组件,它有一个子组件,它使用 GraphQL 从数据库中获取一些数据。在测试父母时,我不在乎孩子在做什么。我想用一个模拟组件(一个不从数据库中获取数据的组件)替换子组件,这样我就可以只关注父组件了。

我想出了一个最简单的例子来说明我的情况。请注意,我使用的是 React Native 和 React Native 测试库。

./src/ParentComponent.js

import React from 'react';
import { Text, View } from 'react-native';
import ChildComponent from './ChildComponent';

const ParentComponent = () => (
  <View>
    <Text>Hello World</Text>
    <ChildComponent />
  </View>
);

export default ParentComponent;

./src/ChildComponent.js

import React from 'react';
import { useQuery } from 'react-apollo';
import { View, Text } from 'react-native';
import gql from 'graphql-tag';

const CURRENT_USER_QUERY = gql`
  query {
    currentUser {
      username
    }
  }
`;

const ChildComponent = () => {
  const { data } = useQuery(CURRENT_USER_QUERY);
  const { username } = data.currentUser;

  return (
    <View>
      <Text>Welcome, {username}</Text>
    </View>
  );
};

export default ChildComponent;

./src/__mocks__/ChildComponent.js

import React from 'react';
import { Text } from 'react-native';

const ChildComponent = () => <Text>Welcome.</Text>;

export default ChildComponent;

./src/ParentComponent.test.js

import React from 'react';
import { MockedProvider } from '@apollo/react-testing';
import { render } from '@testing-library/react-native';
import ParentComponent from '../ParentComponent';

it(`should render the parent component.`, () => {
  jest.mock('../ChildComponent');
  const { getByText } = render(
    <MockedProvider>
      <ParentComponent />
    </MockedProvider>
  );

  expect(getByText('Hello World')).toBeTruthy();
});

当我运行测试时,我收到以下错误...

  ● should render the parent component.

    TypeError: Cannot read property 'currentUser' of undefined

      14 | const ChildComponent = () => {
      15 |   const { data } = useQuery(CURRENT_USER_QUERY);
    > 16 |   const { username } = data.currentUser;
         |                             ^
      17 |
      18 |   return (
      19 |     <View>

      at ChildComponent (src/ChildComponent.js:16:29)

它仍然使用真正的&lt;ChildComponent /&gt;。为什么不将&lt;ChildComponent /&gt; 替换为__mocks__ 目录中的模拟版本?这不是模拟的工作方式吗?如果有人可以请帮助和解释,将不胜感激。谢谢。

【问题讨论】:

  • 你在模拟错误的文件:它应该是 jest.mock(“path-to-mock/__mock__/ChildComponent.js”)
  • 感谢您的回复。我尝试过这个。这也不起作用,根据开玩笑的文档,在该目录中有文件,应该自动选择文件...jestjs.io/docs/en/manual-mocks.html

标签: reactjs mocking jestjs native-testing-library


【解决方案1】:

在为此绞尽脑汁几天之后,我终于弄清楚出了什么问题。我在it 声明中调用了模拟。当我将线 jest.mock('../ChildComponent'); 移到顶部时,一切正常。所以,测试文件应该是这样的……

import React from 'react';
import { MockedProvider } from '@apollo/react-testing';
import { render } from '@testing-library/react-native';
import ParentComponent from '../ParentComponent';

jest.mock('../ChildComponent');

it(`should render the parent component.`, () => {
  const { getByText } = render(
    <MockedProvider>
      <ParentComponent />
    </MockedProvider>
  );

  expect(getByText('Hello World')).toBeTruthy();
});

【讨论】:

  • 我只是来这里说这个,恭喜您解决了您的问题。作为参考,jest 文档:jestjs.io/docs/en/manual-mocks "注意:为了正确模拟,Jest 需要 jest.mock('moduleName') 与 require/import 语句在同一范围内。"
  • 谢谢你,埃里克。有时只需要在 SO 上写一个问题,问题就会显现出来。我现在在文档中看到了这一点。谢谢。
猜你喜欢
  • 2016-03-05
  • 2021-12-10
  • 2020-05-17
  • 2019-02-24
  • 2019-09-03
  • 1970-01-01
  • 2017-10-01
  • 2017-02-13
相关资源
最近更新 更多