2017-02-03 7 views
2

をスパイすることができていてもイベントハンドラをスパイすることはできません。は私が冗談/ジャスミン/酵素を使用してリアクトにイベントハンドラをテストする他の方法

MyComponent.js

import React from 'react'; 
class MyComponent extends React.Component { 
    constructor(props) { 
     super(props); 
     this.clickHandler = this.clickHandler.bind(this); 
     this.otherMethod = this.otherMethod .bind(this); 
    } 

    clickHandler() { this.otherMethod(); } 
    otherMethod() {} 

    render() { return <div onClick={this.clickHandler}/>; } 
} 
export default MyComponent; 

MyComponent.test.js:私は、私は全く同じ2つのコンポーネントのメソッドをスパイだと考えているという事実にもかかわらず

import React from 'react'; 
import {mount} from 'enzyme'; 
import MyComponent from './MyComponent'; 

it('should work',() => { 
    const componentWrapper = mount(<MyComponent/>); 
    const component = componentWrapper.get(0); 

    spyOn(component, 'otherMethod').and.callThrough(); 
    spyOn(component, 'clickHandler').and.callThrough(); 

    componentWrapper.find('div').simulate('click'); 

    expect(component.otherMethod).toHaveBeenCalled(); // works 
    expect(component.clickHandler).toHaveBeenCalled(); // does not work 
}); 

、(otherMethod用)、それらの一方が他方しばらく(clickHandlerのために)機能しません。私は明らかにです。clickHandlerotherMethodと呼ぶことはありませんでしたが、私はそうでない場合は呼び出されませんでしたが、clickHandlerのためにtoHaveBeenCalledが選択されていません。どうして?

私は本当にotherMethod.bind(this)または.and.callThrough()のいずれかを使用する必要はありませんが、私はちょうど同じように2つのメソッドを治療し、otherMethodにそれらを使用すると、実際にどんな違いを作るべきではないの両方を使用することを理解しています。私はリスナーとしてそれを取り付ける前に、機能をスパイする必要が

This other SO answer状態。これは私の問題であれば、私はそれを解決する方法がわからない:spyOn構文は、メソッドが(この場合はcomponent)の財産であることをオブジェクトが必要ですが、componentを使用してリスナーを付けるために私を強制的にMyComponentの前に取り付けが必要です最初。

私のコードではReactを使用しているので、質問タグとしてreactjsを含めることは関係ありますが、どういうわけか私はそれを疑っています。

+1

主な問題は、あなたのコンポーネントの内部にスパイしようということです。通常は、何らかのコールバックをコンポーネントに注入するか、clickイベントの結果として非同期呼び出しを行います。これはコンポーネントの外側から来て、簡単に傍受(コールバック)または嘲笑(非同期呼び出し)することができます。たぶんあなたの例が単純化されているかもしれませんが、 'this.otherMethod()'の結果に焦点を当てるべきです。 –

答えて

2

この種のテストでは、イベントをシミュレートする代わりに、コンポーネントインスタンスのハンドラメソッドを呼び出すことが一般的な方法です。

onClick小道具がリアクションチームによってテストされていることを確かめることができます。何を確認できるかは、「彼ら」があなたのハンドラを呼び出すときに起こります。

これにより、少なくとも私にとってははるかに高速な浅いレンダリングを使用することもできます。あなたのラッパーでinstance()方法で簡単にインスタンスへの参照を取得することができ、あなたは、あなたが好きで、あなたのハンドラとスパイを呼び出すことができます。実際に

const wrapper = mount(<MyComponent />) 
const instance = wrapper.instance() 
instance.clickHandler() 
//assert whatever 

、おそらく(すでにバインドされている)instance`s方法にあなたのスパイを取り付けることにもトリックを行います。 :)

http://airbnb.io/enzyme/docs/api/ReactWrapper/instance.html

はそれが役に立てば幸い!

+0

(1)浅いレンダリングを実演したければ、 'mount ...'の代わりに 'shallow ...'を使った方がいいですか? (2)私は '.instance()'について知らなかった。私は(明らかに) '.get(0)'を使って同じことを達成しましたが、 '.instance()'はより明白だと思います。(3)私は間違いなく_how_だけでなく、何をテストするかについてのあなたの提案を考えます。しかし、私は最初になぜこれをチェックすることが本当に貴重ではなかったとしても、なぜ 'component.clickHandler'が呼び出されなかったのか不思議です。 (4)すでにバインドされたインスタンスメソッドにスパイを付けるというあなたの提案を理解していません。 –

+0

'get 'は' instance'と同じではないと思います。 https://github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/get.md/https://github.com/airbnb/enzyme/blob/master/docs/api/ReactWrapper/get。 md – CharlieBrown

+0

さらに、私は何もデモンストレーションしたくなかっただけで、完全実装が不要であり、私は浅い方法を好むと指摘しました。 – CharlieBrown

関連する問題