2017-02-18 7 views
0

私はEventEmitterを継承する依存クラスを持っています。この依存関係を使用する関数が、発生するイベントに基づいてどのように反応するかをテストする必要があります。どのようにEventEmitterクラスの関数をスタブしますか?テスト対象スタブES6 EventEmitterクラス関数

依存クラス

const EventEmitter = require('events'); 

class FooBar extends EventEmitter { 

    constructor() { 
    super(); 

    this.doingSomething = false; 
    } 

    doSomething() { 
    if (this.doingSomething === false) { 
     this.doingSomething = true; 
     this.emit('startedDoingSomething'); 
    } 
    else { 
     this.emit('alreadyDoingSomething'); 
    } 
    } 
} 

module.exports = FooBar; 

依存部

let Foobar = require('FooBar'); 
let fooBar = new FooBar(); 

exports.myFunction =() => { 
    // Set up listeners 
    fooBar.once('startedDoingSomething',() => { 
    fooBar.removeAllListeners(); 
    // Some functionality 
    console.log('Started Doing Something'); 
    }); 

    fooBar.once('alreadyDoingSomething',() => { 
    fooBar.removeAllListeners(); 
    // Some functionality 
    console.log('Already Doing Something'); 
    }); 

    // Call the event-emitting function 
    fooBar.doSomething(); 
}; 

// Other functions that use fooBar 

スタブを作成するために私がSinonを使用していますが、私は、スタブすることができていません効果的にイベントを発生させるクラス関数です。私は[Feature request] stub emitsのテストをモデル化しましたが、スタブされているイベントエミッタの依存関係がクラスであるため、いくつかの変更を加えなければなりませんでした。

テスト

let chai = require('chai'); 
let sinon = require('sinon'); 
let FooBar = require('FooBar'); 
let dependentModule = require('./dependentModule'); 

describe('Dependent Module',() => { 
    it('alreadyDoingSomething',() => { 
    sinon.stub(FooBar.prototype, 'pause',() => { 
     FooBar.prototype.emit('alreadyDoingSomething'); 
    }); 

    // Assertion statements here 
    expect(dependentModule.myFunction()).to... 
    }); 
}); 

このアプローチは、実際には、スタブ関数が呼び出されているにもかかわらず、イベントを発しありません。

答えて

0

テストでは13行目で、それはdependentModule.myFunction()

を呼び出し、そして、それはテストの下で依存モジュールにライン19に続いてテスト

下に依存部の5行目にジャンプし、それは次にfooBar.doSomething()

を呼び出します依存関係クラスの12行目にジャンプします。this.doingSomethingはfalseであるため、startedDoingSomethingを出力します。

次に、テスト対象の依存モジュールの7行目にジャンプし、fooBar.removeAllListeners();を呼び出します。つまり、同じファイルの34行目に登録されたイベントハンドラも削除されます。

これは意味ですか?

ここでは、7行目のDependent Module Under Testがコメントアウトされているとします。

、テストで13行の後に、それは順番にFooBar.prototype.emit('alreadyDoingSomething');

問題呼び出すFooBar.prototype.emitが呼び出されたときに、コンテキスト内this被試験依存モジュールに2行目で宣言さfooBarと等しくないということであるFooBar.prototype.pause呼び出します。 (FooBar.prototypeに等しい)

したがってFooBar.prototype.emit('alreadyDoingSomething');は、テスト対象の依存モジュールの12行目で定義されたイベントハンドラをトリガしません。

fooBar.emit('alreadyDoingSomething')と連絡する方法を見つける必要があります。

rewireのようなライブラリが使用されていない限り、fooBarはエクスポートされないため、不可能です。

ここでは、被依存モジュールの最後にexports.fooBar = fooBar;を追加するものとします。

また、テストの9行目をthis.emit('alreadyDoingSomething')に変更しました。これは重要です。これは、emitがインスタンスになる必要があるときにコンテキストが必要なためです(fooBar)。

これで、dependentModule.fooBar.pause()が呼び出されると、alreadyDoingSomethingがトリガーされます。

これで、Already Doing Somethingがコンソールに表示されます。

+0

はい - 7行目のremoveAllListeners()呼び出しは意図的です.1つのイベントが発生した後にmyFunctionがハングしないようにするためです。この特定のケースでは、発行されたがすべてのケースを処理する必要がある最初のイベントについてのみ気にします。 removeAllListeners()の呼び出しをコメントしなくても、提案されたエクスポートの修正が機能しますが、クラスのインスタンスではなくコンストラクタだけでこの作業を行う方法がないことは残念です。 –

関連する問題