2016-11-04 36 views
5

我正在構建node.js模塊,我也希望用Jasmine來測試它。用Jasmine攔截Event發送器

讓說我的模塊類似於此:

var myModule = function (foo, bar) { 

    // Begin a workflow 
    var workflow = new (require('events').EventEmitter)(); 

    workflow.on('test', function() { 
    var greet = greet(); 
    return greet; 
    }); 

    workflow.emit('test'); 

}; 

function greet() { 
    return "Hi!"; 
} 

module.exports = { 
    myModule: myModule 
}; 

如何測試我的茉莉針對我的活動我發射模塊?

事情是這樣的:

var myModule = require('../myModule.js');  

describe('My Module test', function() { 

    it('should get greet value', function() { 
    myModule.on('test', function() { // "test" as I wrote in myModule 
     expect(myModule.greet).toHaveBeenCalled(); 
    }); 
    }); 
}); 

回答

0

我做到這一點使用proxyquire:https://github.com/thlorenz/proxyquire

在您的測試文件:

var proxyquire = require('proxyquire'); 
var mockEvents = {}; 
var myModule = proxyquire('../myModule.js', { 
    events: mockEvents 
}); 

describe('My Module test', function() { 
    beforeEach(function() { 
    mockEvents.EventEmitter = function() {}; 

    mockEvents.EventEmitter.prototype = { 
     on: function() { }, 
     emit: function() { } 
    }; 

    spyOn(mockEvents.EventEmitter.prototype, 'on'); 
    spyOn(mockEvents.EventEmitter.prototype, 'emit'); 
    }); 

    it('should get greet value', function() { 
    myModule() 
    expect(mockEvents.EventEmitter.prototype.on).toHaveBeenCalledWith('test'); 
    expect(mockEvents.EventEmitter.prototype.emit).toHaveBeenCalledWith('test'); 
    }); 
}); 

你也可以使用一個諜照你的模擬EventEmitter等

+0

嗨,謝謝你的回答,我可以問一個更詳細的例子嗎?我是新來的單元測試世界,它會更好地理解它更好... –

+0

不知道這個例子是否完全有效,因爲我剛剛寫了它內聯。但你應該閱讀這個:http://jasmine.github.io/2.5/introduction還有關於proxyquire的文檔。 –

+0

我會盡快測試它並讓你知道。謝謝 –

0

主要問題是greet沒有真正暴露,因此在測試中無法訪問。這裏有一些方法來處理這個問題:

  1. 將它添加到原型鏈,使其可以訪問(這是我在下面做了)。

  2. 將函數公開在module.exports中。這可以包裝在process.env.NODE_ENV !== production中以排除生產。

  3. 不公開它,但測試事件發射器功能和功能的影響(這可能不理想)。

達到你想要什麼,你可以猴子修補功能和測試,他們被稱爲和測試的greet單獨的結果:

MyModule.js

var EventEmitter = require('events').EventEmitter; 
var MyModule = function (foo, bar) { 
    // Begin a workflow 
    var workflow = new EventEmitter(); 

    workflow.on('test', function() { 
    return this.greet(); 
    }.bind(this)); 

    workflow.emit('test'); 
}; 

MyModule.prototype.greet = function() { 
    return "Hi!"; 
}; 

module.exports = MyModule; 

MyModule-tests.js

var EventEmitter = require('events').EventEmitter; 

describe('MyModule', function() { 
    it('emits an event upon construction', function() { 
    // Monkey patch 
    var originalEventEmitterOn = EventEmitter.prototype.on; 
    EventEmitter.prototype.on = jasmine.createSpy('on'); 

    // Create module 
    var MyModule = require('./MyModule'); 
    new MyModule(); 
    expect(EventEmitter.prototype.on).toHaveBeenCalled(); 

    // Reset 
    EventEmitter.prototype.on = originalEventEmitterOn; 
    }); 

    it('calls greet upon construction', function() { 
    var MyModule = require('./MyModule'); 

    // Monkey patch 
    var originalGreet = MyModule.prototype.greet 
    MyModule.prototype.greet = jasmine.createSpy('greet'); 

    var myModule = new MyModule(); 
    expect(myModule.greet).toHaveBeenCalled(); 

    // Reset 
    MyModule.prototype.greet = originalGreet; 
    }); 

    it('returns "Hi!"', function() { 
    var MyModule = require('./MyModule'); 
    var myModule = new MyModule(); 
    expect(myModule.greet()).toBe("Hi!"); 
    }); 
});