LoginSignup
13
10

More than 5 years have passed since last update.

enzymeでReactコンポーネントのイベントハンドラをテストしてみた

Last updated at Posted at 2016-11-01

はじめに

前回enzymeの導入について記事を書きました。

これまでは単純にrenderされるDOMのチェックしかしてなかったのですが、今回はonClickなどのハンドラをテストしてみました。
前回同様jestをベースにテストを行っています。

コンポーネント内のメソッドでハンドルしている場合

// 実装
export default class Hoge extends Component {
  render() {
    return (
      <div>
        <a href="#" onClick={this.onClickLink.bind(this)}>Click me</a>
      </div>
    );
  }

  onClickLink(e) {
    e.preventDefault();
    console.log("clicked!");
  }
}

この場合、クリックイベントに対して正しいハンドラが呼ばれているかをテストする必要があるかと思います。
ですので Hoge.prototype.onClick() をモックに差し替えます。

// テスト
describe("Hoge", () => {
  describe("when click link", () => {
    it("call Hoge.prototype.onClick() method", () => {
      const wrapper = shallow(<Hoge />);
      const instance = wrapper.instance(); // これでHogeクラスのインスタンスが取得できる
      const fakeOnClickLink = jest.fn(); // モックを作成
      instance.onClickLink = fakeOnClickLink; // モックで上書き

      wrapper.find("a").simulate("click"); // これだけでclickイベントが発生する!!
      expect(fakeOnClickLink).toBeCalled(); // 呼ばれている
    });
  });
});

SharrowWrapper.prototype.instance() でマウントされたコンポーネントの実体を取得できるため、そのオブジェクトのハンドラをモックで上書きしてしまえばいいみたいです。

input[type="text"]等でstateの変化をテストする場合

// 実装
export default class Hoge extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: ""
    };
  }

  render() {
    const { email } = this.state;
    return (
      <div>
        Email: <input type="email" value={email} onChange={this.onChange.bind(this)}/>
      </div>
    );
  }

  onChangeEmail(e) {
    this.setState({ email: e.target.value });
  }
}

inputのvalueをstateで管理している場合ですね。
この場合はハンドラが呼ばれるだけでなく、stateの更新まで行えるところまでをテストしたいところです。
ですのでテストは以下のようにしました。

// テスト
describe("Hoge", () => {
  describe("when input email", () => {
    it("change email state", () => {
      const wrapper = shallow(<Hoge />);
      const fakeEventObject = { target: { value: "sample@example.com" } };

      // simulateの2番目以降がハンドラの引数に渡されます
      wrapper.find("input").simulate("change", fakeEventObject);
      // stateメソッドで取得したいキー名を指定すると値が返る
      expect(wrapper.state("email")).toBe("sample@example.com");
    });
  });
});

今度はハンドラは元のままにしておいて、changeイベントが起きた時のイベントオブジェクトをfakeに差し替えました。
ShallowWrapper.prototype.state を使い、欲しいstateのキー名を指定することで値を取得できます。

まとめ

いやーenzyme使えば使うほど馴染んできますね。とにかくなんでも簡潔に書けて素晴らしいです。

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10