2017-12-29 34 views
0

私はReact Test Utilitiesを使って自分のコードのユニットテストをしています。私はrenderIntoDocumentに電話してカスタムコンポーネントをレンダリングし、findDOMNodeを使ってレンダリングされたものをテストします。私が実行している問題は、状態を更新して単体テストのコンテキスト内で再レンダリングを効果的にトリガする方法がわからないことです。React DOMを使用した単体テストの状態変更をどのようにトリガできますか?

はここにいくつかのサンプルコードです - コードのコメントに注意を払う:

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import TestUtils from 'react-dom/test-utils'; 
import MyCustomComponent from '../../app/components/MyCustomComponent'; 

describe('My Test Suite',() => { 
    let component, node; 
    test('verify state change',() => { 
     const items = [{'value': '1'}]; 
     component = TestUtils.renderIntoDocument(
      <MyCustomComponent items={items} /> 
     ); 
     node = ReactDOM.findDOMNode(component); 
     expect(node.querySelector('input[type=text]').value).toEqual('1'); 
     component.state.items = [{'value': '2'}]; 
     // do something here to trigger a re-render? 
     expect(node.querySelector('input[type=text]').value).toEqual('2'); 
    }); 
}); 

は、残念ながら、それは単に何もしない状態変数を変更するようです。それは定義されていないので、component.componentWillReceiveProps()に電話することはできません。

私が同じコンポーネントに、新しいコンポーネントで置き換えるのではなく、そのレンダリング関数を呼び出すようにしてください。その理由は、コンポーネントがthis.stateの代わりにthis.propsに基づいて物をレンダリングしていたバグが見つかり、初期値ではなく状態からのデータを常に使用していることを示すテストが必要なためです。

+0

ReactDOM.render(、node);コンポーネントを強制的にレンダリングするには? –

+0

@MarouenMhiriはコンポーネントの新しいインスタンスを効果的に作成するだけではありませんか? (既存のインスタンスを再レンダリングするのではなく) – SoaperGEM

+0

これは、コンポーネントを再マウントする代わりに更新されます。私はこれがあなたが探しているものだと思います。 –

答えて

2

Enzyme(AirBnbから)これにはいくつかの優れたユーティリティがあります。 the dependenciesをインストールする必要がありますが、設定するだけで簡単です。次に、コンポーネントインスタンスでEnzyme's setState methodと呼ぶだけです。重要な注意 - この場合の "コンポーネントインスタンス"はshallow rendered componentです。あなたのコードは次のようになります:

import React from 'react'; 
import MyCustomComponent from '../../app/components/MyCustomComponent'; 
import { shallow, configure } from 'enzyme'; 
import Adapter from 'enzyme-adapter-react-16'; 

// configure your adapter 
configure({ adapter: new Adapter() }); 

describe('My Test Suite',() => { 

    test('verify state change',() => { 
     const items = [{'value': '1'}]; 
     const wrapper = shallow(<MyCustomComponent items={items} />); 

     // find your shallow rendered component and check its value 
     expect(wrapper.find('input[type="text"]').value).toEqual('1'); 

     // set the state of the component 
     wrapper.setState({ items: [{'value': '2'}] }); 

     // state should be updated, make sure its value was properly set 
     expect(wrapper.find('input[type="text"]').value).toEqual('2'); 
    }); 
}); 

このすべては、あなたが適切にあなたのコンポーネントでstateを使用していることを前提としています。あなたの場合、itemspropとして渡されているようです。 propsをコピーしてstateを設定する場合は、戦略を再考することをおすすめします。いずれにしても、このアプローチは、Reactワークでの更新方法と同じである必要があります。コンポーネントをアンマウントして再マウントすることなく、同じコンポーネントインスタンスで操作しています。お役に立てれば。

+0

これは本当に有望です!残念ながら、私はそれを実行しようとするとすぐにこのエラーに遭遇します。 'セレクタの解析に失敗しました:input [type = text]'酵素は簡単なセレクタ式以外のものをサポートしていませんか? – SoaperGEM

+0

酵素がこれを確実にサポートしています - 'セレクターに関するAPIリファレンス:http://airbnb.io/enzyme/docs/api/selector.html –

+0

更新されたサンプルコードをお試しください。 'wrapper.find( 'input [type =" text "]')'に修正しました。これらの二重引用符は重要です!がんばろう! –

関連する問題