我已经使用了Revealing Module Pattern几个月了,我正在寻找这种模式的替代或变体来解决两个问题我的问题目前拥有事件处理程序和可测试性。我知道我可以拿出下面的一些组合来解决我的问题,但我希望找到一个可以持续使用的清洁替代方案,以解决我目前的两个问题。
所以在这个例子中,我对事件处理程序没有任何问题,但是我不能模拟对函数的调用 在功能内进行单独测试:
var Lion = (function () {
// Reference to rawr works as expected when the click event is triggered
function watch() {
document.addEventListener('click', rawr);
}
function rawr() {
console.log('rawr');
}
function attack() {
console.log('attack');
}
/*
* Can't test goCrazy() in isolation. Mocking rawr() and attack()
* has no effect as demonstrated below.
*/
function goCrazy() {
rawr();
attack();
// Important "crazy" logic
}
return {
watch: watch,
rawr: rawr,
attack: attack,
goCrazy: goCrazy
};
}());
module.exports = Lion;
describe('Mock Check', function () {
it('should mock rawr() and attack() and test only goCrazy logic', function () {
var lion = require('Lion');
spyOn(lion, 'rawr').and.reutrnValue(true);
spyOn(lion, 'attack').and.reutrnValue(true);
var crazy = lion.goCrazy();
expect(lion.rawr).toHaveBeenCalled(); // <-- Fails
expect(lion.attack).toHaveBeenCalled(); // <-- Fails
// can't test goCrazy() logic in isolation :(
});
});
this
代替相同模块并使用new
在此示例中,我可以成功模拟对函数内函数的调用,但如果我尝试添加事件处理程序,则在触发事件时this
变为undefined
。
var Lion = function () {
// Reference to 'this' becomes undefined when event is triggered
this.watch = function () {
document.addEventListener('click', this.rawr);
}
this.rawr = function () {
console.log('rawr');
}
this.attack = function () {
console.log('attack');
}
/*
* Can successfully test goCrazy() in isolation by being able to mock
* rawr() and attack() as needed
*/
this.goCrazy = function () {
this.rawr();
this.attack();
// Important "crazy" logic
}
};
module.exports = Lion;
describe('Mock Check', function () {
it('should mock rawr() and attack() and test only goCrazy logic', function () {
var Lion = require('Lion');
var lion = new Lion();
spyOn(lion, 'rawr').and.reutrnValue(true);
spyOn(lion, 'attack').and.reutrnValue(true);
var crazy = lion.goCrazy();
expect(lion.rawr).toHaveBeenCalled(); // <-- Success
expect(lion.attack).toHaveBeenCalled(); // <-- Success
// testing goCrazy logic in isolation :)
});
});
感谢您的时间。如果有必要澄清,请告诉我,我将修改我的帖子。
答案 0 :(得分:1)
这里的实际问题是,事件处理程序丢失了当前对象的上下文。你可以像这样绑定它
document.addEventListener('click', this.rawr.bind(this));
这将确保无论何时调用rawr
,this
内的rawr
都对应于您创建的lion
对象。