2012-04-30 12 views
9

Intentando probar que se llama a un controlador de eventos en un elemento cliqueado con Jasmine. Tenga un objeto "Pad" que contenga un elemento DOM "PadElement", que haga clic. El controlador de eventos es un método en el objeto Pad:¿Jasmine no puede espiar el controlador de eventos?

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; 
} 

La prueba Jasmine:

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(); 
    }); 

Sin embargo, la prueba falla. Tenga en cuenta que se llama al detector de eventos (console.log escribe con éxito con un clic del mouse y con simulateClick), Y si simplemente llamo a testPad.clickHandler() directamente el espía de Jasmine puede recogerlo. ¿Pero qué sucede durante la prueba real? ¿La invocación del manejador de eventos se transfiere a un objeto diferente en el tiempo de ejecución? ¿Cuál es la forma correcta de hacer esto?

Respuesta

6

En realidad se está probando que GRAPH.padElement llama al clickHandler suministrado y no es que this.clickHandler de GRAPH.Pad es llamado por GRAPH.padElement. Cómo lo haría es

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(); 
    }); 

Esto puede sonar poco diferente a lo que está tratando de lograr. Pero en el mundo ideal de pruebas unitarias deberías probar cada unidad de forma independiente, por lo que primero probaría que padElement hace lo que se supone que debe hacer (como arriba) y luego escribir otra prueba para asegurarte de que GRAPH.Pad esté pasando el manejador correcto al padElement. Ahora, para hacer eso, no crearía padElement directamente desde GRAPH.Pad, pero de alguna manera lo inyectaría desde el exterior y luego se burlaría de las especificaciones de jazmín. Si no tiene claro esta parte, hágamelo saber y puedo ponerle un código para usted.

2

Para añadir una explicación más genérica:

Es necesario para espiar antes de conectar la función como un detector de eventos.

algunos pseudo-código:

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 
}); 

Así que si usted sabe que su controlador está siendo llamado, pero el espía no registra como .tohaveBeenCalled() comprobar lo que ocurra primero: el espía o la asignación del oyente. El espía debe ser lo primero.

Cuestiones relacionadas