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的更多討論,有興趣的可以戳 http://hcc0926.blog.51cto.com/172833/1614576 http://hcc0926.blog.51cto.com/172833/1614586 http://hcc0926.blog.51cto.com/172833/1554745
測試依賴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); }); });
參考:http://icodeit.org/2013/12/how-to-test-controller-in-angularjs/