Ich habe myService
diese Verwendungen myOtherService
, die einen Fernanruf tätigen und ein Versprechen zurückgeben:
angular.module('app.myService', ['app.myOtherService'])
.factory('myService', [
myOtherService,
function(myOtherService) {
function makeRemoteCall() {
return myOtherService.makeRemoteCallReturningPromise();
}
return {
makeRemoteCall: makeRemoteCall
};
}
])
Um einen Unit-Test für zu machen, muss myService
ich mich verspotten myOtherService
, so dass seine makeRemoteCallReturningPromise
Methode ein Versprechen zurückgibt. So mache ich es:
describe('Testing remote call returning promise', function() {
var myService;
var myOtherServiceMock = {};
beforeEach(module('app.myService'));
// I have to inject mock when calling module(),
// and module() should come before any inject()
beforeEach(module(function ($provide) {
$provide.value('myOtherService', myOtherServiceMock);
}));
// However, in order to properly construct my mock
// I need $q, which can give me a promise
beforeEach(inject(function(_myService_, $q){
myService = _myService_;
myOtherServiceMock = {
makeRemoteCallReturningPromise: function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
}
};
}
// Here the value of myOtherServiceMock is not
// updated, and it is still {}
it('can do remote call', inject(function() {
myService.makeRemoteCall() // Error: makeRemoteCall() is not defined on {}
.then(function() {
console.log('Success');
});
}));
Wie Sie oben sehen können, hängt die Definition meines Mocks davon ab $q
, mit welcher ich laden muss inject()
. Darüber hinaus sollte das Injizieren des Mocks stattfinden module()
, was vorher kommen sollte inject()
. Der Wert für das Modell wird jedoch nicht aktualisiert, sobald ich es ändere.
Was ist der richtige Weg, um dies zu tun?
javascript
angularjs
unit-testing
mocking
jasmine
Georgii Oleinikov
quelle
quelle
myService.makeRemoteCall()
? Wenn ja, liegt das Problem darin,myService
dass SiemakeRemoteCall
nichts haben und nichts mit Ihrem Verspotteten zu tun habenmyOtherService
.Antworten:
Ich bin mir nicht sicher, warum die Art und Weise, wie Sie es getan haben, nicht funktioniert, aber ich mache es normalerweise mit der
spyOn
Funktion. Etwas wie das:Denken Sie auch daran, dass Sie einen
$digest
Aufruf tätigen müssen, damit diethen
Funktion aufgerufen werden kann. Siehe den Abschnitt Testen in der $ q-Dokumentation .------BEARBEITEN------
Nachdem ich mir genauer angesehen habe, was Sie tun, sehe ich das Problem in Ihrem Code. In der
beforeEach
Einstellung setzen SiemyOtherServiceMock
auf ein ganz neues Objekt. Der$provide
wird diese Referenz nie sehen. Sie müssen nur die vorhandene Referenz aktualisieren:quelle
andCallFake
Sie verwendenandReturnValue(deferred.promise)
(oderand.returnValue(deferred.promise)
in Jasmine 2.0+). Sie müssen natürlich definieren,deferred
bevor Sie anrufenspyOn
.$digest
in diesem Fall anrufen , wenn Sie keinen Zugriff auf den Bereich haben?$rootScope
und ruft das$digest
auf.$q.when()
codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrongWir können auch Jasmins Umsetzung der Rückgabe von Versprechen direkt durch Spion schreiben.
Für Jasmin 2:
(aus Kommentaren kopiert, dank ccnokes)
quelle
spyOn(myOtherService, "makeRemoteCallReturningPromise").and.returnValue($q.when({}));
Ich habe gerade eine halbe Stunde getötet, um das herauszufinden.quelle
Sie können eine Stubbing-Bibliothek wie sinon verwenden, um Ihren Dienst zu verspotten. Sie können dann $ q.when () als Ihr Versprechen zurückgeben. Wenn der Wert Ihres Scope-Objekts aus dem Versprechungsergebnis stammt, müssen Sie scope. $ Root. $ Digest () aufrufen.
quelle
$rootScope.$digest()
, um das Versprechen zu lösenmit
sinon
:Bekannt
httpPromise
kann das sein:quelle
Ehrlich gesagt ... Sie gehen dies falsch an, indem Sie sich auf injizieren, um einen Dienst anstelle eines Moduls zu verspotten. Das Aufrufen von inj in einem beforeEach ist ein Anti-Pattern, da es das Verspotten pro Test erschwert.
Hier ist, wie ich das machen würde ...
Wenn Sie jetzt Ihren Dienst einspeisen, verfügt er über eine ordnungsgemäß verspottete Verwendungsmethode.
quelle
Ich fand diese nützliche, stechende Dienstfunktion als sinon.stub (). Returns ($ q.when ({})):
Regler:
und testen
quelle
Das Code-Snippet:
Kann in einer prägnanteren Form geschrieben werden:
quelle