尝试测试事件处理程序是否被调用到带有 Jasmine 的点击元素上。有一个包含 DOM 元素"PadElement"的"Pad"对象,该元素被单击。事件处理程序是 Pad 对象上的方法:
GRAPH.Pad = function(graphDiv, graph) {
this.graph = graph;
this.clickHandler = function(e) {
console.log('padElement clickHandler called');
//this.graph.createVertex(e.clientX, e.clientY);
};
this.padElement = GRAPH.padElement(graphDiv, this.clickHandler);
}
GRAPH.padElement = function(graphDiv, clickHandler) {
//Initialize pad
var NS="http://www.w3.org/2000/svg";
var pad=document.createElementNS(NS,"svg");
pad.setAttributeNS(null, 'id', 'pad');
graphDiv.appendChild(pad);
pad.addEventListener('click', clickHandler)
return pad;
}
茉莉花测试:
var testDiv = document.createElement('div');
var testGraph = new GRAPH.Graph(testDiv);
var testPad = new GRAPH.Pad(testDiv, testGraph);
it('has its clickHandler function called when its padElement is clicked',
function() {
spyOn(testPad, "clickHandler");
simulateClick(testPad.padElement);
//testPad.clickHandler();
expect(testPad.clickHandler).toHaveBeenCalled();
});
但是,测试失败。请注意,事件侦听器确实被调用(控制台.log通过鼠标单击和模拟点击成功写入),如果我直接调用testPad.clickHandler(),Jasmine的间谍可以拾取它。但是在实际测试中会发生什么?事件处理程序调用是否会在运行时传输到其他对象?正确的方法是什么?
您实际上是在测试GRAPH.padElement
调用提供的clickHandler
,而不是GRAPH.padElement
调用GRAPH.Pad
this.clickHandler
。我会怎么做是
var testDiv = document.createElement('div');
var clickHandlerSpy = jasmine.CreateSpy();
var padelement = padElement(testDiv , clickHandlerSpy);
it('has its clickHandler function called when its padElement is clicked',
function() {
simulateClick(testPad.padElement);
expect(clickHandlerSpy).toHaveBeenCalled();
});
这听起来可能与您想要实现的目标没有什么不同。但是在理想的单元测试世界中,您应该独立测试每个单元,因此我将首先测试padElement
执行它应该执行的操作(如上所述),然后编写另一个测试以确保GRAPH.Pad
将正确的处理程序传递给padElement
。现在要做到这一点,我不会直接从内部创建padElement
GRAPH.Pad
而是以某种方式从外部注入它,然后在茉莉花规格中模拟它。如果您不清楚这部分,请告诉我,我可以为您整理一些代码。
添加更通用的解释:
在将函数附加为事件侦听器之前,您需要进行监视。
一些伪代码:
it("succeeds", function(){
var o = {}
o.f = function() { console.log("event caught!");} //your eventHandler
spyOn(o, "f").and.callThrough(); //o.f is now a spy
addEventListener('click', o.f); //spy listens for event
fireEvent("click"); //"event caught!" is written to console
expect(o.f).toHaveBeenCalled(); //success, we're happy
});
it("fails", function(){
var o = {}
o.f = function() { console.log("event caught!");} //your eventHandler
addEventListener('click', o.f); //your eventHandler function listens for event
spyOn(o, "f").and.callThrough(); //o.f is now a spy
fireEvent("click"); //"event caught!" is written to console
expect(o.f).toHaveBeenCalled(); //fail, we waste a couple of hours not understanding why
});
因此,如果您知道您的处理程序正在被调用,但间谍没有注册为.tohaveBeenCalled()
请检查首先会发生什么:您的间谍或听众的分配。间谍需要排在第一位。