2017-11-21

react-reduxのconnectを使ったコンポーネントをテストする時にInvariant Violationが発生して困っている人のためのヒント

ニッチ過ぎて誰得なのか全くわからないのですが、同じようなことで苦しめられるであろう未来の誰かのために、ここに手がかりを残しておきます。

正直このあたりのライブラリの変化が早過ぎるので、この情報がいつ風化するかわからないのだけれど。。。

はじめに

詰まるところcreate-react-appをベースにReactアプリを作っているのですが、Reduxのconnectを使っているコンポーネントをテストする際に、次のようなエラーが出ました。

これの解決方法を残しておきます。

1
Invariant Violation: You must pass a component to the function returned by connect. Instead received undefined

https://github.com/reactjs/redux/blob/master/docs/recipes/WritingTests.md#connected-components

これを読むと書いてあるんですが、redux storeと一緒テストをする場合は、<Provider>でラップする必要があります。

今回は、redux storeと切り離して純粋なコンポーネントとしてテストする場合の解決方法です。

サンプルコード

例えば、こんなコードです。(ラフに書いたので、このままだと動かないかも)

Component.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import { connect } from 'react-redux';

class Component extends React.Component {
render() {
return <div>{this.props.name}</div>;
}
}

const mapStateToProps = (state) => {
name: state.name,
};

const wrappedComponent = connect(mapStateToProps)(Component);

export default wrappedComponent;

Component.spec.jsx

1
2
3
4
5
6
7
8
9
import * as React from 'react';
import { shallow } from 'enzyme';
import Component from './Component';

describe('Test Component', () => {
it('何かのテスト', () => {
...
});
});

解決方法

上のやり方では、Component.jsxのdefault exportがconnectでラップされたコンポーネントなので、上のエラーが発生していました。

コンポーネント自体をconnectなしでテストするためには、connectでラップされたものの他に、コンポーネント自体もexportする必要があります。

このコンポーネントをテストで利用します。これでエラーも発生しません。

Component.jsx

1
2
3
4
5
6
- class Component extends React.Component {
+ export class Component extends React.Component {
render() {
return <div>{this.props.name}</div>;
}
}

Component.spec.jsx

1
2
3
4
5
6
7
8
9
10
import * as React from 'react';
import { shallow } from 'enzyme';
+ import { Component } from './Component';
- import Component from './Component';

describe('Test Component', () => {
it('何かのテスト', () => {
...
});
});

まとめ

まず、公式ドキュメントに目を通せ!ということでした。

でも、実際に一度困ってみないと、言っている意味がわからないものですねー。