简体   繁体   English

茉莉花无法监视事件处理程序?

[英]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.clickHandlerGRAPH.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM