Posted at

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

More than 1 year has passed since last update.


想定読者

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にはクラスに書いてあるメソッドしか使えないんだな〜」

くらいに思っておけばいいと思います。

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