Angularjs 使用Jasmine测试Angular Controller对承诺返回服务的调用的最佳方法
在寻找一个好答案/样本一周后,我决定发布我的问题 我需要知道如何编写和测试以下内容的最佳方法: 控制器Angularjs 使用Jasmine测试Angular Controller对承诺返回服务的调用的最佳方法,angularjs,testing,mocking,jasmine,promise,Angularjs,Testing,Mocking,Jasmine,Promise,在寻找一个好答案/样本一周后,我决定发布我的问题 我需要知道如何编写和测试以下内容的最佳方法: 控制器 // my.controller.js (function () { 'use strict'; angular.module('myApp.myModule').controller('Awesome', Awesome); function Awesome($http, $state, AwesomeService) { var vm = this; // us
// 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
}
}
})();
服务
// 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;
}
}
})();
我的应用程序可以使用这种结构。我的服务单元测试也可以。
但我不知道如何在控制器上进行单元测试
我试过这样的方法:
规格
不,我不会这样做的 首先,不需要创建模拟服务:您可以注入真实的服务,并监视它 其次,Angular拥有创建承诺和解决承诺所需的一切。无需使用伪
then()
函数创建伪对象
我会这样做:
describe("Awesome Controller Tests", function() {
beforeEach(module('myApp.myModule'));
var vm, awesomeService, $q, $rootScope;
beforeEach(inject(function($controller, _awesomeService_, _$q_, _$rootScope_) {
$q = _$q_;
awesomeService = _awesomeService_;
$rootScope = _$rootScope_;
vm = $controller('Awesome');
}));
it("Should return an awesome message", function () {
spyOn(awesomeService, "awesomeThingToDo").and.returnValue(
$q.when({
awesomeMessage: 'awesome message'
}));
vm.awesomeThingToDo();
// at this time, the then() callback hasn't been called yet:
// it's called at the next digest loop, that we will trigger
$rootScope.$apply();
// now the then() callback should have been called and initialized
// the message in the controller with the message of the promise
// returned by the service
expect(vm.awesomeMessage).toBe('awesome message');
});
});
无关注释:1.2.28相当旧。您应该迁移到最新版本。我用一个可能的(错误的)解决方案更新了这个问题:
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
}
}
});
我使用回调传递模拟参数并调用实际实现:D我会更新角度版本。。。但我现在不能做(但我用解决方案更新了问题。:D谢谢!你的解决方案太冗长,而且不是最优的:承诺应该是异步的,但你的测试使它同步。你应该更喜欢我在回答中解释的基于承诺的解决方案。你是对的。我的解决方案不够好。我尝试应用你的解决方案,注入服务,使用$q…但我收到了以下错误:错误:意外请求:GET/my backend/api/awesome这意味着要么你没有发现服务方法,要么在发现服务方法之前调用了服务方法。如果你发布的是真实代码,而你使用的是我的测试代码,我看不出这是怎么回事。如果没有,那么发布您尝试的实际代码。这只是一个示例代码。实际代码有一点不同:一些控制器方法在
init()
上被调用。其中一些方法调用服务方法。问题再次更新。;)
describe("Awesome Controller Tests", function() {
beforeEach(module('myApp.myModule'));
var vm, awesomeService, $q, $rootScope;
beforeEach(inject(function($controller, _awesomeService_, _$q_, _$rootScope_) {
$q = _$q_;
awesomeService = _awesomeService_;
$rootScope = _$rootScope_;
vm = $controller('Awesome');
}));
it("Should return an awesome message", function () {
spyOn(awesomeService, "awesomeThingToDo").and.returnValue(
$q.when({
awesomeMessage: 'awesome message'
}));
vm.awesomeThingToDo();
// at this time, the then() callback hasn't been called yet:
// it's called at the next digest loop, that we will trigger
$rootScope.$apply();
// now the then() callback should have been called and initialized
// the message in the controller with the message of the promise
// returned by the service
expect(vm.awesomeMessage).toBe('awesome message');
});
});
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
}
}
});