2014-03-13 7 views
7

Ich habe eine Funktion in meinem Angular-Controller, der wie folgt aussieht:Angular JS - Testen eine Funktion mit einer Seite Redirect Mit Karma/Jasmin

$scope.myFunction = function(){ 
    $scope.myVariable = "something"; 
    $scope.myOtherVariable = "something else"; 
    window.location.href = "/path/to/page"; 
} 

Ein einfacher Jasmin Test deckt die obige Funktion und wie folgt aussieht:

describe('my test', function(){ 
    it('should pass', function(){ 
     scope.myFunction(); 
     expect(scope.myVariable).toBe('something'); 
     expect(scope.myOtherVariable).toBe('something else');  
    }); 
}); 

der obige Test selbst geht, aber dann wirft Karma den folgenden Fehler in der Konsole:

Einige Ihre Tests haben eine volle Seite neu geladen!

Die Seitenumleitung bewirkt, dass Karma diese Warnung auslöst. Was ist der beste Weg, um dies zu umgehen?

Ich dachte darüber nach, sowohl anonyme Funktionen im Jasmin-Test und Angular-Namen und dann arguments.callee.caller.name innerhalb der ursprünglichen Funktion zu geben, um festzustellen, ob die Funktion von sich selbst oder Jasmin aufgerufen wird. Leider gibt arguments.callee.caller.name immer undefined zurück, was vermutlich durch die Art verursacht wird, wie Angular und Jasmine miteinander verknüpft sind.

+0

Dieses Problem tauchte nicht wirklich in meinem Code auf, aber es gab mir den Funken, der eine Reparatur für mein eigenes entzündete, also danke für das Posten! Falls Sie neugierig sind, das Problem, das ich aufgrund Ihrer Frage für mich selbst behoben habe, ist http://stackoverflow.com/questions/31947852/how-to-test-angular-app-with-john-papa-style-karma- und-Jasmin-mit-Daten-servi. Danke, C§ – CSS

Antwort

22

Eine lange Zeit, seit dieser Frage gestellt wurde, aber der folgende Ansatz sollte sauberer sein: die ursprüngliche Funktion zu verwenden Angular des $ Fenster Dienst anstelle des Browserfenster Objekts Durch Ändern

ist es möglich, einen Test zu schreiben Dies erfordert keine Änderung des Produktionscodes oder die Berücksichtigung von Laufzeitparametern. Dies erfordert natürlich, dass $ window eine Abhängigkeit für den Controller ist, wo die Funktion gefunden wird.

angular-mocks/ngMock verwenden, so etwas wie:

var fakeWindow = { 
    location: { 
    href: '' 
    } 
} 
// instantiate controller with mock window 
beforeEach(inject(function($controller) { 
    $controller('YourCtrlName', { 
    $window: fakeWindow 
    }); 
})); 

sollte der Test erlauben Annahme zu passieren, dass der Controller nicht mehr als $ Fenster für etwas anderes benötigt.

+0

perfekteste Antwort ich denke, – Maksym

+0

In den meisten Browsern ist die 'window.location' eine nicht beschreibbare Eigenschaft, also ist das Liefern eines eigenen gefälschten Objekts der beste Weg, diese nicht beschreibbaren Eigenschaften nachzuahmen. – user2943490

+0

Dies sollte die akzeptierte Antwort sein. Sie sollten den Zielcode nicht ändern müssen, damit die Tests so ausgeführt werden, wie es die derzeit angenommene Antwort tut. – Red3

4

Sie könnten nur eine Funktion erstellen, die die Navigation wie

$scope.Navigate = function() { 
    window.location.href = "/path/to/page"; 
}; 

oder noch besser

app.factory('navigator', function() { 
    return { 
     Navigate: function(path) { 
      window.location.href = path; 
     } 
    }; 
}); 

Dann in Ihrem Test in einem gewissen Dienst tut man einen Spion auf navigieren kann, um sicher, dass die Navigation aufgerufen wurde, aber nicht tatsächlich die Navigation aufrufen.

Verwandte Themen