これは、堅牢なテストソリューションのためにJestEnzymeの両方を使用してReact/Reduxアプリをテストする4部構成のシリーズのパート2です。 このパートでは、Reactコンポーネントをテストする方法に関するいくつかの簡単な例を取り上げます。

シリーズ

Reactコンポーネントのテストに関しては、通常のJavaScript関数のテストよりも少し複雑になります。 幸いなことに、コンポーネントのパブリックインターフェイスをテストしているだけです。 入力(props)と出力(レンダリングされるもの)はまだあります。

このシリーズのパート1を読んでフォローすると、さらに良いニュースがあります。 すでにJestとEnzymeがインストールおよびセットアップされています。 これらの2つのライブラリを組み合わせると、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();
    });
  });
});

...

関連する()メソッドは、現在のラッパーのレンダリングされた非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()メソッドを使用すると、関数を簡単にモックしてスパイすることができます。

スマートコンポーネントのテスト

アクションとレデューサーをカバーするテストを通じて、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()を呼び出すことにより、コンポーネントの小道具にアクセスできます。

ボーナスのヒント!

Jestの前は、多くの単体テストがMochaまたはJasmineで作成されていました。 特にexpect()フレーバーのアサーションを使用している場合は、これらのテストをJestに簡単に移植できます。 test()の代わりにit()を保持することもでき、実行する必要があります。 または、test()に更新する場合は、検索と置換が最適です。

次は何ですか?

このシリーズのパート1では、JestとEnzymeのインストールとセットアップの方法を紹介しました。 パート3では、Reduxアクションのテストに移ります。 パート4で終了し、Reduxレデューサーをテストする方法を紹介します。 乞うご期待!