2016-07-12 10 views
3

反応成分をテストするのに酵素/モカを使用しています。Enzyme/Mocha:子コンポーネントからonChangeイベントを発生させて反応コンポーネントの機能をテストする方法

私はテストしている親コンポーネントを持っています。

let wrapper = mount(<Parent />); 

と私は私の両親fooの機能をテストできるように、この親はそれで子コンポーネントを持つ関数

render: function() { 
    <Child onChange={this.foo} /> 
}, 
foo: function() { 
    console.log("I was called"); 
} 

をレンダリングだ、私は火に子供ののonChange機能をしたいと思います。

これまでのところ、私はこれを行う方法が見つかっていません - 私はサイロンとスタブについて読んだことがありますが、それは主に機能を傍受し、発砲しないことです。それは私の子と親を結ぶコード行をテストするものではありませんし、ケースには、私は私の子供のためのユニットテストを書いていないので、

次の試験

shallow(<Parent />).instance().foo(); 

は弱いテストであり、それ子のonChange機能もテストしません。私見 - 親/子に私の部品を壊すことは少ないテスト容易性を意味している場合 - その後、何かがこのフレームワーク

と間違っているすべてのヘルプは感謝

+0

親テストで 'foo()'メソッドをテストし、子供テストで 'props.onChange()'( 'sinon.spy()'を使って)をトリガーする子供の能力をテストすると、子どもが 'props.onChange'を呼び出すと、Reactが' this.foo'を呼び出せることをテストする必要はありません。ちょうどあなたが状態を変更するときにReactが 'render()'を呼び出すか、または小道具が変わるときに 'componentWillReceiveProps()'を呼び出すかをテストする必要はありません。 –

答えて

8

これは私が多くのテストで行ったことです。私にとって最良の方法を見つけたのは、子コンポーネントのonChangeハンドラを手動で呼び出して、結果として起こると予想される動作に基づいてアサーションを作成することです。

import React from 'react'; 
import Child from './child'; 

export default class extends React.Component { 
    render() { 
     return (
      <div> 
       <Child onChange={this.foo} /> 
      </div> 
     ); 
    } 

    foo() { 
     console.log('bar'); 
    } 
} 

onChange小道具が呼び出されたときに文字列「バー」をログに記録する子に渡さ:

それでは、あなたはこのようになります親コンポーネントを持っているとしましょう。これはテストしたい動作です。これを行うために、我々は、以下の手順を実行する必要があります:

  1. スタブconsole.log(私はこの例ではSinonを使用することがあります)お好みのモックライブラリを使用して

  2. の浅いインスタンスを作成します。 Parentコンポーネントを作成し、そのChildへの参照を取得します。

  3. 子のonChange propを手動で呼び出します。

  4. console.logは一度呼ばれていたと主張し、単一の引数で:

    import Foo from './foo'; 
    
    import React from 'react'; 
    import {shallow} from 'enzyme'; 
    
    import sinon from 'sinon'; 
    import sinonChai from 'sinon-chai'; 
    import chai, {expect} from 'chai'; 
    
    describe('Foo',() => { 
        let renderedElement; 
    
        function renderComponent() { 
         const componentElement = React.createElement(Foo); 
    
         renderedElement = shallow(componentElement); 
        } 
    
        before(() => { 
         chai.use(sinonChai); 
        }); 
    
        it('should log the string "bar" when the child component is changed',() => { 
         //step 1 
         sinon.stub(console, 'log'); 
    
         //step 2 
         renderComponent(); 
         const childComponent = renderedElement.props().children; 
    
         //step 3 
         childComponent.props.onChange(); 
    
         //step 4 
         expect(console.log).to.have.callCount(1); 
         expect(console.log).to.be.calledWith('bar'); 
    
         //clean up 
         console.log.restore(); 
        }); 
    }); 
    

    : 'バー' ここ

そして、私は(モカとチャイを使用して)それを行うだろうかですこのアプローチが好きなのは、テストコンポーネントのの動作がなので、単に別の関数と同じように機能する小道具として関数が渡されたことを単にテストするのではないからです。

0

部品にテストを破壊してみ、理解されるであろう。たとえば...まず

、期待される機能は、あなたの子コンポーネントに渡されたことをテスト:私は、私はコンポーネントでレンダリングされているほとんどない時には、上記の単純な matchesElementアプローチを使用したい

import { shallow } from 'enzyme'; 

const actual = shallow(<Parent />); 
const expected = <Child onChange={actual.instance().foo} /> 

expect(actual.matchesElement(expected)).true; 

findセレクタを使用してChildインスタンスを見つけてテストすることもできます。

その後別々あなたのfoo関数をテストする:

import { shallow } from 'enzyme'; 

const actual = shallow(<Parent />).instance().foo(); 
const expected = 'expected return of foo' 

expect(actual).equals(expected); 

あなたは別途ごChildコンポーネントをテストすることができ、それがどのように処理するか、それは、onChange小道具です。

酵素APIのは、ここで使用されているのいくつか:

+0

これは悪い考えではありませんが、一般的にテスト機能ではなく、比較文字列です。マッチと単純なチェックの違いは何ですか?レンダリング関数はコミットごとに変更されませんでしたか?また、親には約10個のコンポーネントが含まれていて、私はその質問を単純化していました。 – NiRR

+0

例を下に私のコメントを参照してください:複雑なレンダリングの場合は、 'find' APIを使って子を探し出し、期待どおりに装飾されていると主張してください。 – ctrlplusb

関連する問題