[英]Jasmine can't spy on event handler?
Trying to test that an event handler gets called on a clicked element with Jasmine. 尝试测试事件处理程序是否已通过Jasmine在clicked元素上调用。 Have a "Pad" object that contains a DOM element "PadElement", which gets clicked. 有一个“ Pad”对象,其中包含一个被单击的DOM元素“ PadElement”。 The event handler is a method on the Pad object: 事件处理程序是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;
}
The Jasmine test: 茉莉花测试:
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();
});
However, the test FAILS. 但是,测试失败。 Note that the event listener does get called (console.log writes successfully with a mouse click and with simulateClick), AND if I just call the testPad.clickHandler() directly Jasmine's spy can pick it up. 请注意,确实会调用事件侦听器(console.log使用鼠标单击并通过SimulationClick成功写入),并且如果我直接调用testPad.clickHandler(),Jasmine的间谍可以将其拾取。 But what happens during the actual test? 但是在实际测试期间会发生什么? Does the event handler invocation get transferred to a different object at runtime? 事件处理程序调用是否在运行时转移到另一个对象? What's the right way to do this? 什么是正确的方法?
You are actually testing that GRAPH.padElement
calls the supplied clickHandler
and not that this.clickHandler
of GRAPH.Pad
is called by GRAPH.padElement
. 你实际上是考验这个GRAPH.padElement
调用提供的clickHandler
并不算this.clickHandler
的GRAPH.Pad
被称为GRAPH.padElement
。 How I would do that is 我会怎么做
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();
});
This may sound little different to what you are trying to achieve. 这听起来可能与您要实现的目标几乎没有什么不同。 But in ideal unit testing world you should be testing each unit independently, so I would first test that padElement
does what it's supposed to do (as above) and then write another test to make sure GRAPH.Pad
is passing correct handler to padElement
. 但是,在理想的单元测试环境中,您应该独立地测试每个单元,因此我将首先测试padElement
是否按照预期进行操作(如上所述),然后编写另一个测试以确保GRAPH.Pad
将正确的处理程序传递给padElement
。 Now to do that I would not create padElement
directly from within GRAPH.Pad
but somehow inject it from outside and then mock it in the jasmine specs. 现在要做的是,我不会直接从GRAPH.Pad
内部创建padElement
,而是以某种方式从外部注入它,然后在茉莉花规格中对其进行模拟。 If you are not clear on this part let me know and I can put some code together for you. 如果您对此部分不清楚,请告诉我,我可以为您添加一些代码。
To add a more generic explanation: 要添加更通用的解释:
You need to spy before attaching the function as an event listener . 在将功能附加为事件侦听器之前,您需要监视 。
Some pseudo-code: 一些伪代码:
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
});
So if you know your handler is being called, but the spy does not register as .tohaveBeenCalled()
check what happens first: your spy or the assignment of the listener. 因此,如果您知道您的处理程序正在被调用,但间谍未注册为.tohaveBeenCalled()
请先检查发生了什么:您的间谍或侦听器的分配。 The spy needs to come first. 间谍必须先到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.