38
20

More than 5 years have passed since last update.

Enzymeのshallowとinstanceの違いに関して

Posted at

想定読者

enzyme、jest触りはじめの方
enzymeのshallowとinstanceの違いがわからないぞという方

Enzymeのshallowとinstanceの違いがわからなかった...

最近Jest+enzymeでテストコードを書いてるんですが、いまいちshallowとinstanceの違いがわからなくてモヤモヤしてたんですがようやくわかったのでメモしてます。

まずshallowってなに?

Enzymeには3つのレンダリング方法があります。
1. Shallow Rendering
2. Full DOM Rendering
3. Static Rendering
です。

これらの違いの説明は公式サイトに任します!

shallow Renderingはその中の1つのレンダリング方法です。
shallow(浅い)という意味通り「浅くやるんだな〜」くらいに思っておいていいと思います。(最初は)
今回はこのshallow Renderingの中でshallow()とinstance()を使って行きたいと思います。

shallow( )はどうやって使うの?

describe('<MyComponent/>のテストだよ', () => {
  it('shallow()をつかって見るよ', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper.find(Foo)).to.have.length(3);
  });
});

こんな感じで使います。

shallow( )を使うことによってShallowWrapperなるものができます。
それに対してfind( )、html( )といったメソッドを使うことで色々なテストができるのです。
find( )、html( )といったメソッドの詳しい使い方はこちら

じゃあinstance( )ってなんだよ

ここできました。instance。
実際のコードは以下になります。

describe('shallowのテストだよ', () => {
  it('instance()つかって見るよ', () => {
    const wrapper = shallow(<MyComponent />);
    const inst = wrapper.instance();
    expect(inst).to.be.instanceOf(MyComponent);
  });
});

なにやらshallow()を使った後にwrapperに対してinstance()を使っていますね。
instance()は文字どおりインスタンス(実体)を作成するメソッドです。
正確に言うとReactComponentを返すメソッドです。

ここで疑問が生まれます。
ShallowWrapperと何が違うんだよという疑問です。
ShallowWrapperもインスタンスっぽい雰囲気を醸し出してるので一瞬インスタンスなのか
と思いそうになるんですが違います。
今から違いを書いていこうと思います。

ShallowWrapperとinstanceの違い

一言で言うと
shallow()で作成したShallowWrapperに対してはEnzyme側が提供しているメソッドを全て使うことができます。
さっきでてきたfind()やらhtml()やらそんな感じのやつです。

それに対して、instance()を用いて作成したインスタンスにはEnzymeが提供しているメソッドを使うことができません。コンポーネントに書いてあるメソッドだけは使うことができます。

以下の具体例で確認します。

例えばこんなクラスがあるとします。

human.tsx
class Human extends React.Component {
  handleClick = () {
    console.log("クリックされたわ〜");
  };

  render() {
    return (
      <div>こんにちは</div>
    );
  }
}

これをテストする際のテストスクリプトはshallow()だけを使う場合、

human.test.tsx
describe('<Human/>をテストするよ', () => {
  it('shallow()だけ使ってみるよ', () => {
    const wrapper = shallow(<Human />);
    wrapper.find('div');
  });
});

のような感じでEnzymeが用意しているfind()メソッドを使うことができます。

今度はinstance( )を使ったコードを見てみます。

human2.test.tsx
describe('<Human/>をテストするよ', () => {
  it('instance()を使ってみるよ', () => {
    const wrapper = shallow(<Human />);
    const instance = wrapper.instance()
    wrapper.find('div');    // これはもちろんOK
    instance.find('div');   // find()はHumanクラスに無いのでエラーがでます。
    instance.handleClick(); // HumanクラスにhandleClick()があるので、これならオッケー
  });
});

と言うような感じになります。

まとめると
「instance()を使って生成したReactComponentにはクラスに書いてあるメソッドしか使えないんだな〜」
くらいに思っておけばいいと思います。

間違いがありましたら教えていただけると嬉しいです〜

38
20
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
38
20