使用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。 敬请关注!