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



在我正在从事的项目中,我真的被困在这个问题上,我找到的所有答案似乎都很简单,但它们对我不起作用。也许我真的不明白什么是模拟,我真的可以使用一些指导。

我正在测试一个父组件,该组件具有使用 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)

它仍在使用真正的<ChildComponent />。为什么不将<ChildComponent />替换为__mocks__目录中的模拟版本?这不就是模拟的工作方式吗?如果有人能帮忙解释一下,将不胜感激。谢谢。

经过几天的绞尽脑汁,我终于弄清楚出了什么问题。我在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();
});

最新更新