Nach einer Woche auf der Suche nach einer guten Antwort/Probe, habe ich mich entschieden, meine Frage zu posten.Der beste Weg Jasmine zu benutzen, um Angular Controller Calls zu Services mit Promise zu testen
Ich muss wissen, wie ist der beste Weg, und Test etwas zu kodieren:
-Controller
// my.controller.js
(function() {
'use strict';
angular.module('myApp.myModule').controller('Awesome', Awesome);
function Awesome($http, $state, AwesomeService) {
var vm = this; // using 'controllerAs' style
vm.init = init;
vm.awesomeThingToDo = awesomeThingToDo;
vm.init();
function awesomeThingToDo() {
AwesomeService.awesomeThingToDo().then(function (data) {
vm.awesomeMessage = data.awesomeMessage;
});
}
function init() {
vm.awesomeThingToDo(); // Should be ready on page start
}
}
})();
Dienst
// my.service.js
(function() {
'use strict';
angular.module('myApp.myModule').factory('AwesomeService', AwesomeService);
function AwesomeService($resource, $http) {
var service = {
awesomeThingToDo: awesomeThingToDo
}
return service;
function awesomeThingToDo() {
var promise = $http.get("/my-backend/api/awesome").then(function (response) {
return response.data;
});
return promise;
}
}
})();
Meine App mit dieser Struktur OK funktioniert. Und meine Service Unit Tests sind auch in Ordnung. Aber ich weiß nicht, wie Unit-Tests auf Controller zu tun.
Ich habe versucht, so etwas wie dieses:
Specs
// my.controller.spec.js
(function() {
'use strict';
describe("Awesome Controller Tests", function() {
beforeEach(module('myApp.myModule'));
var vm, awesomeServiceMock;
beforeEach(function() {
awesomeServiceMock = { Is this a good (or the best) way to mock the service?
awesomeThingToDo: function() {
return {
then: function() {}
}
}
};
});
beforeEach(inject(function ($controller) {
vm = $controller('Awesome', {AwesomeService : awesomeServiceMock});
}));
it("Should return an awesome message", function() {
// I don't know another way do to it... :(
spyOn(awesomeServiceMock, "awesomeThingToDo").and.callFake(function() {
return {
then: function() {
vm.awesomeMessage = 'It is awesome!'; // <-- I think I shouldn't do this.
}
}
});
vm.awesomeThingToDo(); // Call to real controller method which should call the mock service method.
expect(vm.awesomeMessage).toEqual('It is awesome!'); // It works. But ONLY because I wrote the vm.awesomeMessage above.
});
});
})();
Meine app Angular 1.2.28 und Jasmin 2.1.3 (mit Grunt und Karma) verwendet.
UPDATE: Gelöst!
it("Should return an awesome message", function() {
// Solved with callback parameter
spyOn(awesomeServiceMock, "awesomeThingToDo").and.callFake(function(callback) {
return {
then: function(callback) {
callback({awesomeMessage: 'It is awesome!'}); //callback call works fine! :D
}
}
});
Ich würde die Angular-Version aktualisieren ... Aber ich kann es jetzt nicht tun. :( Aber ich aktualisierte die Frage mit der Lösung.: D Danke! –
Ihre Lösung ist sowohl zu ausführlich, und nicht optimal: das Versprechen soll asynchron sein, aber Ihr Test macht es synchron. Sie sollten das Versprechen vorziehen basierte Lösung, die in meiner Antwort erklärt wird –
Sie haben Recht.Meine Lösung ist nicht gut genug. Ich versuchte, Ihre Lösung anzuwenden, injizieren den Service, mit $ q ... aber ich erhielt diesen Fehler: Fehler: Unerwartet request: GET/my-backend/api/awesome –