angularjs中的controller主要负责业务逻辑的处理、数据模型,页面元素的展示等,通常一个controller会依赖一个或者多个service,通过service从数据库拉数据后保存到controller,controller的简陋的例子如下:
app.controller('EventController',['$scope','EventService',function($scope,EventService){ EventService.getEvents().then(function(events){ $scope.events=events; }); }]);
实际项目中的Service可能是这个样子的:
app.factory('EventService', ['$http', '$q', function($http, $q) { return { getEvents: function() { var deferred = $q.defer(); $http.get('/events.json').success(function(result) { deferred.resolve(result); }).error(function(result) { deferred.reject(result); }); return deferred.promise; } }; }]);
通常是返回一个Promise,当数据都加载完成后执行controller中的then方法,关于Promise的更多讨论,有兴趣的可以戳
测试依赖service的controller
通常来讲,在单元级别的测试中,我们不希望Service真正的发送请求,只是需要一个模拟的service,这个service只存在于我们要测试的controller中。我们先看一个例子:
var app = angular.module('MyApp');describe("EventController", function() { var scope, q; var controllerFactory; var mockSerivce = {}; var events = ["event1", "event2", "event3"]; //注入controller所需要的angular服务, beforeEach(function() { module("MyApp"); inject(function($rootScope, $controller, $q) { controllerFactory = $controller; scope = $rootScope.$new(); q = $q; }); });//mock一个service,通过jasmine的createSpy方法创建一个替代方法,当调用service的相关方法时返//回这个替代方法,数据被包含到promise中, beforeEach(function() { var deferred = q.defer(); deferred.resolve(events); mockSerivce.getEvents = jasmine.createSpy('getEvents'); mockSerivce.getEvents.andReturn(deferred.promise); });//通过这个方法实例化controller function initController() { return controllerFactory('EventController', { $scope: scope, EventService: mockSerivce }); }//每次测试controller都要实例化一次controller it("should have a events list", function() { initController(); scope.$digest(); expect(scope.events.length).toEqual(3); expect(scope.events).toEqual(events); });});
参考: