Enzyme / Reactテストでレンダーとシャローをいつ使用すべきですか?


95

この質問を投稿する前に、sqa stackexchangeで検索してみましたが、浅い投稿は見つかりませんでした。そこで、誰かが私を助けてくれるといいのですが。

反応コンポーネントのテストでシャローおよびレンダリングを使用する必要があるのはいつですか?airbnb docsに基づいて、私は2つの違いについていくつかの意見を述べました:

  1. シャローはコンポーネントを1つの単位としてテストするので、「親」コンポーネントに使用する必要があります。(例:テーブル、ラッパーなど)

  2. レンダーは子コンポーネント用です。

私がこの質問をした理由は、どちらを使用するべきかを判断するのに苦労しているためです(ドキュメントには非常によく似ていると記載されていますが)。

それで、特定のシナリオでどれを使用するかをどうやって知るのですか?


2
浅い()とマウント()の違いは、浅い()がコンポーネントをレンダリングする子コンポーネントから分離してコンポーネントをテストする一方で、マウント()がより深くなり、コンポーネントの子をテストすることです。シャロー()の場合、これは、親コンポーネントがレンダリングに失敗した別のコンポーネントをレンダリングした場合、親でのシャロー()レンダリングが引き続き成功することを意味します。
Shyam Kumar

回答:


160

酵素のドキュメントによると

mount(<Component />) 完全なDOMのレンダリングは、DOM APIと相互作用するコンポーネントがある場合、またはコンポーネントを完全にテストするために完全なライフサイクルが必要な場合(つまり、componentDidMountなど)のユースケースに最適です。

shallow(<Component />) 浅いレンダリングは、コンポーネントを1つのユニットとしてテストするように制限し、テストが子コンポーネントの動作を間接的にアサートしないようにするのに役立ちます。

renderこれは、コンポーネントを静的HTMLにレンダリングし、結果のHTML構造を分析するために使用されます。

それでも、浅いレンダーで基礎となる「ノード」を表示できるため、たとえば、スペックランナーとしてAVAを使用して、次のような(少し工夫された)例を実行できます。

let wrapper = shallow(<TagBox />);

const props = {
    toggleValue: sinon.spy()
};

test('it should render two top level nodes', t => {
    t.is(wrapper.children().length, 2);
});

test('it should safely set all props and still render two nodes', t => {
    wrapper.setProps({...props});
    t.is(wrapper.children().length, 2);
});

test('it should call toggleValue when an x class is clicked', t => {
    wrapper.setProps({...props});
    wrapper.find('.x').last().simulate('click');
    t.true(props.toggleValue.calledWith(3));
});

お知らせそのレンダリング小道具を設定し、セレクタを発見しても、合成のイベントはすべて、浅いレンダリングによってあなたはちょうどそれを使用することができますので、ほとんどの時間をサポートしています。

ただし、コンポーネントのライフサイクル全体を取得することはできないため、componentDidMountで発生することが予想される場合は、を使用する必要がありますmount(<Component />)

このテストでは、Sinonを使用してコンポーネントのスパイを行いますcomponentDidMount

test.only('mount calls componentDidMount', t => {

    class Test extends Component {
        constructor (props) {
            super(props);
        }
        componentDidMount() {
            console.log('componentDidMount!');
        }
        render () {
            return (
                <div />
            );
        }
    };

    const componentDidMount = sinon.spy(Test.prototype, 'componentDidMount');
    const wrapper = mount(<Test />);

    t.true(componentDidMount.calledOnce);

    componentDidMount.restore();
});

上記は、浅いレンダリングまたはレンダリングでは通過しません

render はHTMLのみを提供するので、次のようなことができます。

test.only('render works', t => {

    // insert Test component here...

    const rendered = render(<Test />);
    const len = rendered.find('div').length;
    t.is(len, 1);
});

お役に立てれば!


1
私はまだ100%を取得しません。なぜ3つの動詞が異なる方法をもたらすのですか。たとえば、wrapper.getNode()をシャローで使用できますが、レンダーでは使用できません。この説明を取得するのに役立つ説明/リンク/ドキュメント/ブログはありますか?
Paulquappe 2017

@HenryZhuは、特定のコンポーネントノードのDOMツリーを模倣しようとするため、レンダリングが浅いよりも複雑であることをドキュメントから明確にする必要があります
AGE



9

浅い()とマウント()の違いは、浅い()がコンポーネントをレンダリングする子コンポーネントから分離してコンポーネントをテストする一方で、マウント()がより深くなり、コンポーネントの子をテストすることです。

シャロー()の場合、これは、親コンポーネントがレンダリングに失敗した別のコンポーネントをレンダリングした場合、親でのシャロー()レンダリングが引き続き成功することを意味します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.