使用 Jest 测试时如何用模拟替换 React 组件

Śān*_*anu 8 mocking reactjs jestjs react-native-testing-library

在我正在从事的项目中,我真的很困惑,我找到的所有答案似乎都很简单,但它们对我不起作用。也许我不太明白模拟是什么,我真的需要一些指导。

\n\n

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

\n\n

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

\n\n

./src/ParentComponent.js

\n\n
import React from \'react\';\nimport { Text, View } from \'react-native\';\nimport ChildComponent from \'./ChildComponent\';\n\nconst ParentComponent = () => (\n  <View>\n    <Text>Hello World</Text>\n    <ChildComponent />\n  </View>\n);\n\nexport default ParentComponent;\n
Run Code Online (Sandbox Code Playgroud)\n\n

./src/ChildComponent.js

\n\n
import React from \'react\';\nimport { useQuery } from \'react-apollo\';\nimport { View, Text } from \'react-native\';\nimport gql from \'graphql-tag\';\n\nconst CURRENT_USER_QUERY = gql`\n  query {\n    currentUser {\n      username\n    }\n  }\n`;\n\nconst ChildComponent = () => {\n  const { data } = useQuery(CURRENT_USER_QUERY);\n  const { username } = data.currentUser;\n\n  return (\n    <View>\n      <Text>Welcome, {username}</Text>\n    </View>\n  );\n};\n\nexport default ChildComponent;\n
Run Code Online (Sandbox Code Playgroud)\n\n

./src/__mocks__/ChildComponent.js

\n\n
import React from \'react\';\nimport { Text } from \'react-native\';\n\nconst ChildComponent = () => <Text>Welcome.</Text>;\n\nexport default ChildComponent;\n
Run Code Online (Sandbox Code Playgroud)\n\n

./src/ParentComponent.test.js

\n\n
import React from \'react\';\nimport { MockedProvider } from \'@apollo/react-testing\';\nimport { render } from \'@testing-library/react-native\';\nimport ParentComponent from \'../ParentComponent\';\n\nit(`should render the parent component.`, () => {\n  jest.mock(\'../ChildComponent\');\n  const { getByText } = render(\n    <MockedProvider>\n      <ParentComponent />\n    </MockedProvider>\n  );\n\n  expect(getByText(\'Hello World\')).toBeTruthy();\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我运行测试时,出现以下错误...

\n\n
  \xe2\x97\x8f should render the parent component.\n\n    TypeError: Cannot read property \'currentUser\' of undefined\n\n      14 | const ChildComponent = () => {\n      15 |   const { data } = useQuery(CURRENT_USER_QUERY);\n    > 16 |   const { username } = data.currentUser;\n         |                             ^\n      17 |\n      18 |   return (\n      19 |     <View>\n\n      at ChildComponent (src/ChildComponent.js:16:29)\n
Run Code Online (Sandbox Code Playgroud)\n\n

依然用的是真实的<ChildComponent />。为什么它不替换目录<ChildComponent />中的模拟版本__mocks__?这不是模拟的工作原理吗?如果有人可以帮助和解释,我们将不胜感激。谢谢。

\n

Śān*_*anu 4

经过几天的绞尽脑汁,我终于弄清楚出了什么问题。我在声明中调用了模拟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();
});
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你,埃里克。有时只需要在 SO 上写下一个问题,问题就会暴露出来。我现在在文档中看到了这一点。谢谢。 (2认同)