2017-02-18 1 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()

그런 다음이 테스트에서 종속 모듈에 5 행으로 점프

그런 다음 테스트에서 종속 모듈 라인 (19), 그것은 그런 fooBar.doSomething()

호출이 종속성 클래스의 12 번째 줄로 이동하면 this.doingSomething이 거짓이므로 startedDoingSomething을 내 보냅니다.

그런 다음 테스트중인 종속 모듈에서 7 행으로 이동하고 fooBar.removeAllListeners();을 호출합니다. 이는 동일한 파일의 34 행에 등록 된 이벤트 처리기도 제거됨을 의미합니다.

이것이 의도입니까?

이제 7 행의 종속 모듈이 fooBar.removeAllListeners으로 간주됩니다.

및 테스트 라인 (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).

이제 Test에서 dependentModule.fooBar.pause()이 호출되면 alreadyDoingSomething이 트리거됩니다.

이제 콘솔에 Already Doing Something이 표시되어야합니다.

+0

예 - 7 행의 removeAllListeners() 호출은 의도적입니다. 이는 단일 이벤트가 발생한 후에 myFunction이 어슬렁 거리지 않도록하기위한 것입니다. 이 특별한 경우, 나는 방출되었지만 모든 경우를 다루어야하는 첫 번째 사건에 대해서만 신경을 썼다. removeAllListeners() 호출에 주석을 추가하지 않고도 제안 된 내보내기 수정이 작동하지만 클래스의 정확한 인스턴스 대신 생성자 만 사용하여이 작업을 수행 할 수있는 방법이 없다는 점을 유감스럽게 생각합니다. –