1

私のテストスイートで、関数*であるクラスのプロパティをスタブするにはどうすればよいですか? 通常のメソッドを使用すると、見つかった各メソッドを簡単に使用Object.getOwnPropertyNames(component.prototype)してモンキーパッチを適用できますが、長い間苦労した後、クラスのフィールドに割り当てることによって作成された関数を抽出する方法が見つかりませんでした。

私のテスト スタックは、Jest と Jasmine2 および babel で構成されています。

トランスパイルの問題は、アロー関数プロパティが (もちろん予想どおり) トランスパイルされた出力「クラス」のインスタンス (実際にはもちろん関数) に割り当てられることです。したがって、このオブジェクトをインスタンス化する以外にそれらをスタブ化する方法はありません。入力 es7 コードと babel の出力の例を次に示します。ただし、私はこのソリューションが特に好きではありません。非常にハックなようです。このソリューションのもう 1 つの欠点は、コンポーネントのクラスを直接インスタンス化できないことです。


(*) この質問の背景は、es7 のようなクラスで記述された React コンポーネントの単体テストであり、自動バインドの目的でクラスのプロパティにアロー関数が割り当てられています。

4

2 に答える 2

2

私が取り組んでいるプロジェクトの単体テストを書いているとき、私は同じ問題を抱えていました。それを解決するための良いパターンを得たと思います。うまくいけば、それは役に立ちます:

環境

handleClickこれは、太い矢印表記を使用して定義されたメソッドを持つ React コンポーネントの例です。

import React, { Component } from 'react';

class Foo extends Component {
  componentWillMount() {
    this.handleClick();
  }

  handleClick = (evt) => {
    // code to handle click event...
  }

  render() {
    return (
      <a href="#" onClick={this.handleClick}>some foo link</a>
    );
  }
}

問題

このリンクで説明されているように、 Babelはコードをトランスパイルして、handleClickメソッドがインスタンス化後にのみ使用できるようにします (生成されたコンストラクター関数の31 行目から 33 行目を確認してください)。

ここでの問題は、クラスをインスタンス化する前に、太い矢印表記を使用して定義されたメソッドにアクセスする必要がある場合があることです。

たとえば、クラス メソッドの単体テストを作成していて、目的の単体テストのみをテストできるようcomponentWillMountに をスタブ化したい場合を考えてみましょう。しかし、インスタンス化後にhandleClickしかアクセスできず、インスタンス化ライフサイクルの一部としてメソッドが自動的に呼び出されるため、問題があります。handleClickcomponentWillMountReact

解決

このような問題を解決するために簡単なパターンを適用する方法は次のとおりです。

import React from 'react';
import { mount } from 'enzyme';
import { expect } from 'chai';
import sinon from 'sinon';

import Foo from './foo';

describe('Foo', () => {
  describe('componentWillMount method', () => {
    const handleClickStub = sinon.stub();
    class FooWrapper extends Foo {
      constructor(props) {
        super(props);
        this.handleClick = handleClickStub;
      }
    }

    it('should register a click event listener to the externalElement property', () => {
      handleClickStub.reset();
      mount(<FooWrapper />);
      expect(handleClickStub.calledOnce).to.be.true;
    });
  });
});

説明

Foo元のコンポーネントを初期化した後、元のコンポーネントをコンストラクターのwhere にラップしました。元のメソッドをスタブ バージョンFooWrapperに置き換えて、クラスのプロパティ テストを行います。handleClickcomponentWillMount

于 2016-10-02T17:14:02.887 に答える