使用Jest和Enzyme测试React/Redux应用程序-第2部分:测试React组件

来自菜鸟教程
跳转至:导航、​搜索

这是使用 JestEnzyme 测试 React / Redux 应用程序的 4 部分系列的第 2 部分,以获得强大的测试解决方案。 在这一部分中,我们将介绍一些关于如何测试 React 组件的简单示例。

该系列

在测试 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 之前,很多单元测试都是用 MochaJasmine 编写的。 您可以轻松地将这些测试移植到 Jest,尤其是在您使用 expect() 风格的断言时。 您甚至可以保留 it() 代替 test() 并且它们应该运行。 或者,如果您想将内容更新为 test(),那么查找和替换是您最好的朋友。

下一步是什么?

在本系列的第 1 部分中,我向您展示了如何安装和设置 Jest 和 Enzyme。 现在在第 3 部分中,我们将继续测试 Redux 操作。 我们将在第 4 部分结束,我将向您展示如何测试 Redux reducer。 敬请关注!