揭示用于测试的模块替代或变体
Revealing Module Alternative or Variation for Testing
概览
我已经使用 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;
示例测试用例 (Jasmine)
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;
示例测试用例 (Jasmine)
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 :)
});
});
感谢您的宝贵时间。如果需要任何说明,请告诉我,我会修改我的 post.
这里的实际问题是,事件处理程序丢失了当前对象的上下文。你可以这样绑定
document.addEventListener('click', this.rawr.bind(this));
这将确保每当调用 rawr
时,rawr
中的 this
对应于您创建的 lion
对象。
概览
我已经使用 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;
示例测试用例 (Jasmine)
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;
示例测试用例 (Jasmine)
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 :)
});
});
感谢您的宝贵时间。如果需要任何说明,请告诉我,我会修改我的 post.
这里的实际问题是,事件处理程序丢失了当前对象的上下文。你可以这样绑定
document.addEventListener('click', this.rawr.bind(this));
这将确保每当调用 rawr
时,rawr
中的 this
对应于您创建的 lion
对象。