2012-03-25 8 views
2

Wenn Sie ein Objekt vortäuschen, das Sinon.js verwendet und eine Eigenschaft hat, die als Callback an jQuery.delegate weitergegeben wird, scheitern Ihre Erwartungen wenn Sie die Methode auslösen, die in jQuery.delegate beobachtet wird. Wenn Sie die Methode innerhalb des Rumpfes einer anonymen Funktion ausführen, die Sie als Rückruf für jQuery.delegate verwenden, werden Ihre Erwartungen erfüllt.Objekte, die mit Sinon.js verspottet werden, bestätigen nicht, dass ihre Methoden über einen jQuery.delegate-Callback ausgeführt werden

 
test("FAILS: Handler is invoked as callback from jQuery delegate method directly...", function() { 
    var Controller, 
     View, 
     $el, 
     c, 
     v, 
     mock; 

    Controller = function() { 
     var self = {}; 

     self.handler = function(e) { 
      console.log("got handled"); 
     }; 

     return self; 
    }; 

    View = function($el, controller) { 
     var self = {}; 

     self.render = function() { 
      $el.html(""); 

      $el.delegate("#derp", "keyup", controller.handler); 
     }; 

     return self; 
    }; 

    $el = jQuery(""); 
    c = new Controller(); 
    v = new View($el, c); 
    mock = this.mock(c); 

    v.render(); 

    mock.expects("handler").once(); 

    $el.find("input").val("bar").trigger("keyup"); 
    equal($el.find("input").val(), "bar"); // passes! 

    mock.verify(); 
}); 
 
test("WINS: Handler is invoked inside anonymous function...", function() { 
    var Controller, 
     View, 
     $el, 
     c, 
     v, 
     mock; 

    Controller = function() { 
     var self = {}; 

     self.handler = function(e) { 
      console.log("got handled"); 
     }; 

     return self; 
    }; 

    View = function($el, controller) { 
     var self = {}; 

     self.render = function() { 
      $el.html(""); 

      $el.delegate("#derp", "keyup", function(e) { 
       controller.handler(e); 
      }); 
     }; 

     return self; 
    }; 

    $el = jQuery(""); 
    c = new Controller(); 
    v = new View($el, c); 
    mock = this.mock(c); 

    v.render(); 

    mock.expects("handler").once(); 

    $el.find("input").val("bar").trigger("keyup"); 
    equal($el.find("input").val(), "bar"); // passes! 

    mock.verify(); 
}); 

mache ich hier etwas falsch?

Danke,

Erin

+0

Ich muss zustimmen, wenn v2 funktioniert dann sollte auch v1. Schlägt v1 auch mit einem tatsächlichen keyup fehl? Scheitert v1 auch beim Testen mit '.triggerHandler (" keyup ")'? –

Antwort

0

Dies ist ein klassischer callback scope Gotcha. Funktionsargumente liegen außerhalb des Gültigkeitsbereichs, daher verfügt controller über keine handler-Methode, da sie nicht lokal definiert ist. Die anonyme Funktion gibt ihr Geltungsbereich, weil Funktionen den Bereich in JavaScript steuern.