Ich habe einen AngularJS-Dienst geschrieben und möchte ihn einem Unit-Test unterziehen.
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) {
this.something = function() {
// Do something with the injected services
};
return this;
});
In meiner Datei app.js sind folgende Dateien registriert:
angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)
Ich kann testen, ob der DI als solcher funktioniert:
describe("Using the DI framework", function() {
beforeEach(module('fooServiceProvider'));
beforeEach(module('barServiceProvider'));
beforeEach(module('myServiceProvder'));
var service;
beforeEach(inject(function(fooService, barService, myService) {
service=myService;
}));
it("can be instantiated", function() {
expect(service).not.toBeNull();
});
});
Dies hat bewiesen, dass der Dienst vom DI-Framework erstellt werden kann. Als Nächstes möchte ich den Dienst jedoch einem Unit-Test unterziehen, was bedeutet, dass die injizierten Objekte verspottet werden.
Wie mache ich das?
Ich habe versucht, meine Scheinobjekte in das Modul einzufügen, z
beforeEach(module(mockNavigationService));
und Umschreiben der Service-Definition als:
function MyService(http, fooService, barService) {
this.somthing = function() {
// Do something with the injected services
};
});
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) { return new MyService($http, fooService, barService); })
Letzteres scheint jedoch zu verhindern, dass der Dienst wie alle anderen vom DI erstellt wird.
Weiß jemand, wie ich die injizierten Dienste für meine Unit-Tests verspotten kann?
Vielen Dank
David
javascript
angularjs
mocking
jasmine
angularjs-service
BanksySan
quelle
quelle
Antworten:
Sie können Mocks in Ihren Service einfügen, indem Sie
$provide
.Wenn Sie den folgenden Dienst mit einer Abhängigkeit haben, die eine Methode namens getSomething hat:
Sie können eine Scheinversion von myDependency wie folgt einfügen:
Beachten Sie, dass
$provide.value
Sie myDependency aufgrund des Aufrufs nicht explizit irgendwo einfügen müssen. Dies geschieht unter der Haube während der Injektion von myService. Wenn Sie hier mockDependency einrichten, kann es sich genauso gut um einen Spion handeln.Vielen Dank an loyalBrown für den Link zu diesem großartigen Video .
quelle
beforeEach(module('myModule'));
Anruf HAS vor dem kommendenbeforeEach(function () { MOCKING })
Anruf, oder aber die Mocks durch die realen Leistungen erhalten überschrieben werden!$provide
Anrufe getätigt werden, bevor sie$injector
anderweitig verwendet werden. Sie erhalten eine Fehlermeldung:Injector already created, can not register a module!
Error: [ng:areq] Argument 'fn' is not a function, got Object
, stellen Sie sicher, dass Sie danach einreturn
in die Zeile einfügen$provide.value(...)
. Die implizite Rückgabe$provide.value(...)
hat diesen Fehler für mich verursacht.So wie ich es sehe, besteht keine Notwendigkeit, die Dienste selbst zu verspotten. Verspotten Sie einfach die Funktionen des Dienstes. Auf diese Weise können Sie Ihre realen Dienste wie in der gesamten App eckig injizieren lassen. Verspotten Sie dann die Funktionen des Dienstes nach Bedarf mithilfe der Jasmine-
spyOn
Funktion.Wenn der Dienst selbst eine Funktion und kein Objekt ist, mit dem Sie arbeiten können
spyOn
, gibt es einen anderen Weg, dies zu tun. Ich musste das tun und fand etwas, das für mich ziemlich gut funktioniert. Siehe Wie verspotten Sie den Angular-Dienst, der eine Funktion ist?quelle
Eine weitere Option, um das Verspotten von Abhängigkeiten in Angular und Jasmine zu vereinfachen, ist die Verwendung von QuickMock. Es ist auf GitHub zu finden und ermöglicht es Ihnen, einfache Mocks auf wiederverwendbare Weise zu erstellen. Sie können es von GitHub über den unten stehenden Link klonen. Die README-Datei ist ziemlich selbsterklärend, kann aber hoffentlich in Zukunft anderen helfen.
https://github.com/tennisgent/QuickMock
Es verwaltet automatisch alle oben genannten Boilerplates, sodass Sie nicht bei jedem Test den gesamten Scheininjektionscode ausschreiben müssen. Hoffentlich hilft das.
quelle
Zusätzlich zu John Galambos 'Antwort : Wenn Sie nur bestimmte Methoden eines Dienstes verspotten möchten, können Sie dies folgendermaßen tun:
quelle
Wenn Ihr Controller so geschrieben ist, dass er eine Abhängigkeit wie diese berücksichtigt:
dann können Sie
someDependency
in einem Jasmin-Test wie folgt eine Fälschung machen :quelle
Ich habe kürzlich ngImprovedTesting veröffentlicht, das Mock-Tests in AngularJS einfacher machen soll.
Um 'myService' (aus dem "myApp" -Modul) mit seinen verspotteten fooService- und barService-Abhängigkeiten zu testen, können Sie in Ihrem Jasmine-Test einfach Folgendes tun:
Weitere Informationen zu ngImprovedTesting finden Sie in seinem einführenden Blog-Beitrag: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/
quelle
Ich weiß, dass dies eine alte Frage ist, aber es gibt noch einen einfacheren Weg: Sie können ein Mock erstellen und das bei einer Funktion injizierte Original deaktivieren. Dies kann mithilfe von spyOn für alle Methoden erfolgen. siehe Code unten.
quelle