web-dev-qa-db-ja.com

SinonでReactコンポーネントメソッドをスタブする

テスト目的で React コンポーネントメソッドをスタブ化しようとしています。

var Comp = React.createClass({
  displayName: "Comp",

  plop: function() {
    console.log("plop");
  },

  render: function() {
    this.plop();
    return React.DOM.div(null, "foo");
  }
});

var stub = sinon.stub(Comp.type.prototype, "plop");
React.addons.TestUtils.renderIntoDocument(Comp());
sinon.assert.called(stub); // throws

悲しいことに、これはコンソールに「プロップ」を印刷し続けます…そしてアサーションは失敗します。

注:仕様オブジェクトメソッドを直接スタブすることはできますが、コンポーネントコンストラクタと仕様を別々にエクスポートして、両方がテストで使用できるようにする必要があります。また、コンポーネントクラスを作成する前に、仕様をスタブする必要があります。それほど便利ではありません:

var CompSpec = {
  displayName: "Comp",

  plop: function() {
    console.log("plop");
  },

  render: function() {
    this.plop();
    return React.DOM.div("foo");
  }
};

var stub = sinon.stub(CompSpec, "plop");
var Comp = React.createClass(CompSpec);
React.addons.TestUtils.renderIntoDocument(Comp());

// plop() is properly stubbed, so you can
sinon.assert.called(stub); // pass

Reactコンポーネントメソッドを簡単にスタブ化するための別の戦略を考えられますか?

22
NiKo

Reactの auto-binding feature に対して実行しています。これは、クラスメソッドをラップする.bind(this)をキャッシュします。キャッシュされたバージョンのメソッドをReactの__reactAutoBindMapでスタブすることにより、コードを機能させることができます。

var Comp = React.createClass({
  displayName: "Comp",

  plop: function() {
    console.log("plop");
  },

  render: function() {
    this.plop();
    return React.DOM.div(null, "foo");
  }
});

// with older versions of React, you may need to use
// Comp.type.prototype instead of Comp.prototype
var stub = sinon.stub(Comp.prototype.__reactAutoBindMap, "plop");  // <--
React.addons.TestUtils.renderIntoDocument(React.createElement(Comp));
sinon.assert.called(stub);  // passes
29
danvk

どのテストフレームワークを使用していますか?

あなたがジャスミンを使用している場合、私は jasmine-react がReactメソッドをスパイし、コンポーネントをテストスタブで置き換えるための便利なライブラリであることを発見しました。

この場合、コンポーネント定義の外でメソッドを簡単にスパイできます。

_//Component Definition
var Comp = React.createClass({

    displayName: "Comp",

    plop: function() {
       console.log("plop");
    },

    render: function() {
       this.plop();
       return React.DOM.div(null, "foo");
    }
});

//test
it("should call plop method on render", function(){
   //spy on method
   jasmineReact.spyOnClass(Comp, "plop");
   React.addons.TestUtils.renderIntoDocument(Comp());
   expect(Comp.plop).toHaveBeenCalled();
})
_

_jasmineReact.spyOnClass_は、呼び出しとその引数の追跡に使用できる通常のジャスミンスパイを返します。

実際にメソッドをスタブして何かを返すようにしたい場合は、jasmineReact.spyOnClass(Comp, "plop").andReturn('something')のようなことを行うことができます

別の方法として、Facebookは最近テストフレームワーク Jest (依存関係としてジャスミンも含む)を起動しました。テストフレームワークは、テストに自身を使用しますReactコンポーネント。これを使用してコンポーネントメソッドを簡単にスタブできます。これもチェックする価値があるように見えますが、commonJSモジュール内にコンポーネントを作成すると、おそらくもう少し独自のものになります。

5
Ron