这是测试React / Redux应用程序的4部分系列中使用Jest和Enzyme进行测试的强大测试解决方案的第2部分,在本部分中,我们将涵盖如何测试React组件的一些简单示例。
系列
- Part 1: Installation & Setup
- Part 2: Testing React Components (this post)
- Part 3: Testing Redux Actions
- Part 4: Testing Redux Reducers
当涉及到测试 React 组件时,事情比测试常规 JavaScript 函数要多一些。好消息是,您仍然只是测试您的组件的公共接口。
如果你阅读并遵循这个系列的 ** 部分 1** 还有更好的消息. 你已经安装了 Jest 和 Enzyme 并安装了. 这些两个库结合了大量测试 React 组件的痛苦。
何以进口
1[label __tests__/components/GatorMenu.test.js]
2import React from 'react';
3import { shallow } from 'enzyme';
4import toJson from 'enzyme-to-json';
5import configureStore from 'redux-mock-store'; // Smart components
6
7// Component to be tested
8import GatorMenu from '../../components/GatorMenu';
9
10...
<$>[注]从酶的 shallow()
方法将当前节点渲染,并返回周围的浅包裹,这允许您对单元测试保持忠诚,只测试组件,而不是对儿童进行主张。
<$>[注]从酶到Json的 toJson()
方法将 Enzyme 包装转换为与 Jest snapshot 测试兼容的格式。
<$>[注] redux-mock-store 的 configureStore()
方法用于帮助嘲笑与您的 Redux 商店的互动。
测试你的组件
1[label __tests__/components/GatorMenu.test.js]
2...
3
4describe('<GatorMenu />', () => {
5 describe('render()', () => {
6 test('renders the component', () => {
7 const wrapper = shallow(<GatorMenu />);
8 const component = wrapper.dive();
9
10 expect(toJson(component)).toMatchSnapshot();
11 });
12 });
13});
14
15...
<$>[注] dive()方法返回当前包装器的非DOM子女。如果您的组件将另一个组件包装成某种类似的DIV元素,而您对测试感兴趣的是该内部组件,这将变得有用。
模拟事件
以下是模拟在渲染元件上的点击
事件的一个示例. 我们使用平面渲染元件的查找
方法来找到一个元素,然后将返回元件上的模拟
方法称为字符串:
1[label __tests__/components/GatorButton.test.js]
2...
3
4describe('<GatorButton />', () => {
5 describe('onClick()', () => {
6 test('successfully calls the onClick handler', () => {
7 const mockOnClick = jest.fn();
8 const wrapper = shallow(
9 <GatorButton onClick={mockOnClick} label="Eat Food" />
10 );
11 const component = wrapper.dive();
12
13 component.find('button').simulate('click');
14
15 expect(mockOnClick.mock.calls.length).toEqual(1);
16 });
17 });
18});
19
20...
<$>[注] jest.fn()方法允许您轻松地嘲笑和监视函数。
智能组件测试
我建议通过涵盖您的行动和减量剂的测试来测试您与 Redux 商店的互动。 尝试并将您的组件测试集中在被渲染的内容和客户端行为上。
1[label __tests__/components/GatorAvatar.test.js]
2import { Avatar } from 'react-native-elements';
3
4...
5
6const mockStore = configureStore();
7const initialState = {
8 selectReducer: {
9 selectedAvatar: 0,
10 },
11 avatars: [
12 {
13 name: 'Green Gator',
14 image: 'https://cdn.alligator.io/images/avatars/green-gator.jpg',
15 },
16 {
17 name: 'Yellow Gator',
18 image: 'https://cdn.alligator.io/images/avatars/yellow-gator.jpg',
19 },
20 {
21 name: 'Blue Gator',
22 image: 'https://cdn.alligator.io/images/avatars/blue-gator.jpg',
23 },
24 ],
25};
26const store = mockStore(initialState);
27
28describe('<GatorAvatar />', () => {
29 test('dispatches event to show the avatar selection list', () => {
30 const wrapper = shallow(<GatorAvatar store={store} />);
31 const component = wrapper.dive();
32
33 component.find(Avatar).props().onPress();
34
35 expect(store.getActions()).toMatchSnapshot();
36 });
37});
38
39...
正如你所看到的,我们可以通过在一个元素上调用props()
来访问组件的代理。
奖金提示!
在 Jest 之前,许多单元测试都是用 Mocha或 Jasmine编写的。你可以很容易地将这些测试转移到 Jest,特别是如果你正在使用声明的「expect()」味道。
什么是下一步?
在本系列的第1部分中,我向您展示了如何安装和设置Jest和Enzyme。现在在第3部分中,我们将继续测试Redux操作。我们将在第4部分结束,在那里我将向您展示如何测试Redux减速器。