使用Jest和Enzyme测试React/Redux应用程序-第2部分:测试React组件
这是使用 Jest 和 Enzyme 测试 React / Redux 应用程序的 4 部分系列的第 2 部分,以获得强大的测试解决方案。 在这一部分中,我们将介绍一些关于如何测试 React 组件的简单示例。
该系列
- 第1部分 : 安装和设置
- 第 2 部分:测试 React 组件(这篇文章)
- 第 3 部分:测试 Redux 操作
- 第四部分:测试Redux Reducers
在测试 React 组件时,比测试常规 JavaScript 函数涉及更多的事情。 好消息是您仍然只是在测试组件的公共接口。 您仍然有一个输入(props)和输出(它呈现的内容)。
如果您阅读并关注了本系列的 第 1 部分 ,将会有更好的消息。 您已经安装并设置了 Jest 和 Enzyme。 这两个库结合起来抽象了测试 React 组件的许多痛苦。
导入什么
__tests__/components/GatorMenu.test.js
import React from 'react';
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import configureStore from 'redux-mock-store'; // Smart components
// Component to be tested
import GatorMenu from '../../components/GatorMenu';
...
Enzyme 的 shallow() 方法渲染当前节点并返回围绕它的浅包装。 这使您可以忠实于单元测试,只测试组件,而不是对子组件进行断言。
从酶到 JSON 的 toJson() 方法将酶包装器转换为与 Jest 快照测试兼容的格式。
redux-mock-store 中的 configureStore() 方法用于帮助模拟与 Redux 存储的交互。 只有连接到商店的智能组件才需要。
测试你的组件渲染
__tests__/components/GatorMenu.test.js
...
describe('<GatorMenu />', () => {
describe('render()', () => {
test('renders the component', () => {
const wrapper = shallow(<GatorMenu />);
const component = wrapper.dive();
expect(toJson(component)).toMatchSnapshot();
});
});
});
...
dive() 方法返回当前包装器的呈现的非 DOM 子级。 如果您的组件将另一个组件包装在 div 元素之类的东西中,并且您有兴趣测试的是该内部组件,这将变得很有用。
模拟事件
这是一个模拟渲染组件上的 click 事件的示例。 我们使用浅渲染组件的 find 方法找到一个元素,然后在返回的元素上调用 simulate 方法,并将事件名称作为字符串传入:
__tests__/components/GatorButton.test.js
...
describe('<GatorButton />', () => {
describe('onClick()', () => {
test('successfully calls the onClick handler', () => {
const mockOnClick = jest.fn();
const wrapper = shallow(
<GatorButton onClick={mockOnClick} label="Eat Food" />
);
const component = wrapper.dive();
component.find('button').simulate('click');
expect(mockOnClick.mock.calls.length).toEqual(1);
});
});
});
...
jest.fn() 方法允许您轻松地模拟和监视函数。
测试智能组件
我建议通过涵盖你的 action 和 reducer 的测试来测试你与 Redux 商店的交互。 尝试让您的组件测试专注于正在呈现的内容和客户端行为。 话虽如此,您可以在智能组件中测试与商店的交互:
__tests__/components/GatorAvatar.test.js
import { Avatar } from 'react-native-elements';
...
const mockStore = configureStore();
const initialState = {
selectReducer: {
selectedAvatar: 0,
},
avatars: [
{
name: 'Green Gator',
image: 'https://cdn.alligator.io/images/avatars/green-gator.jpg',
},
{
name: 'Yellow Gator',
image: 'https://cdn.alligator.io/images/avatars/yellow-gator.jpg',
},
{
name: 'Blue Gator',
image: 'https://cdn.alligator.io/images/avatars/blue-gator.jpg',
},
],
};
const store = mockStore(initialState);
describe('<GatorAvatar />', () => {
test('dispatches event to show the avatar selection list', () => {
const wrapper = shallow(<GatorAvatar store={store} />);
const component = wrapper.dive();
component.find(Avatar).props().onPress();
expect(store.getActions()).toMatchSnapshot();
});
});
...
如您所见,我们可以通过在元素上调用 props() 来访问组件的 props。
奖金提示!
在 Jest 之前,很多单元测试都是用 Mocha 或 Jasmine 编写的。 您可以轻松地将这些测试移植到 Jest,尤其是在您使用 expect() 风格的断言时。 您甚至可以保留 it() 代替 test() 并且它们应该运行。 或者,如果您想将内容更新为 test(),那么查找和替换是您最好的朋友。
下一步是什么?
在本系列的第 1 部分中,我向您展示了如何安装和设置 Jest 和 Enzyme。 现在在第 3 部分中,我们将继续测试 Redux 操作。 我们将在第 4 部分结束,我将向您展示如何测试 Redux reducer。 敬请关注!