2013-01-09 104 views
11

我想測試一個使用角度$資源的控制器。

function PermissionsCtrl($scope, $resource, $cookies) { 
    var Object = $resource('/v1/objects/:id'); 
    loadObjects(); 

    function loadObjects() { 
    $scope.myAppObjects = new Array(); 

    var data = AppObject.get({find: '{"app_id": '+wtm.app_id+'}'}, 
     function(){ 
     if (data.results) { 
      for(var i = 0; i< data.results.length; i++) { 
      if(!data.results[i].is_deleted) { 
       (function(i){ 
       $scope.objects(data.results[i]); 
       }(i)); 
      } 
      } 
     } 
     }, 
     function(error){console.log(error);}); 
    } 

這裏是測試代碼。

var apiServer = "..."; 
var app_id = 999 
var mock_object_data = {...}; 


describe('apps permissionsCtrl', function(){ 
    var scope, ctrl, $httpBackend; 

    // Create a matcher for comparing data 
    beforeEach(function() { 
    this.addMatchers({ 
     toEqualData: function(expected) { 
     return angular.equals(this.actual, expected); 
     } 
    }); 
    }); 

    // Create the controller with injected data/services 
    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller, $resource) { 
    $httpBackend = _$httpBackend_; 
    // cookie data to inject 
    var cookies = new Array(); 
    cookies['id'] = '...'; // just needs to be declared 


    $httpBackend.expectGET(apiServer+'/v1/app_objects? find=%7B%22app_id%22:'+app_id+'+%7D&access_token=' + cookies['id']) 
     .respond(mock_object_data); 

    var $injector = angular.injector(['ng', 'ngResource']); 
    var $resource = $injector.get('$resource'); 

    scope = $rootScope.$new(); 
    ctrl = $controller(PermissionsCtrl, {$scope: scope, $cookies: cookies, $resource: $resource}); 
    })); 

    it('should put object data into $scope', function() { 
    $httpBackend.flush(); 
    expect(scope.objects).toEqualData(mock_object_data); 

}); });

當我運行此我得到

Error: Unknown provider: $resourceProvider <- $resource 

在那裏我嘗試創建我的控制線。我不明白如何將此注入到控制器中,無論我嘗試什麼,我都會得到相同的錯誤。我試過的一些東西是

  • 聲明一個空的模擬對象,並通過類似於我的cookie變量傳遞它。我認爲這可能是一個不好的解決方案,因爲我真的想使用該服務。
  • 模仿範圍模擬並將其傳遞到我的注入函數並將$ resource。$ new()傳遞給我的控制器。
  • 什麼也不做,希望httpBackend能夠覆蓋它,因爲無論如何這最終都會被調用。 VojtaJína讓它聽起來像是有用,但沒有骰子。
  • 輕度貶義。滿意但不是很有效。

回答

6

後多讀多的嘗試,似乎這樣做的正確方法是抽象的使用$資源進行控制的。在我的情況下,我編寫了一個依賴於$ resource的服務,然後將該服務注入到我的控制器中。同時我會從我的控制器中單獨測試該服務。更好的練習。

我的服務宣言:

angular.module('apiModule', ['localResource', 'ngCookies']) 
.factory('apiService', function($resource, $cookies) { 

,在我的單元測試,我通過它傳遞的beforeEach設置功能

beforeEach(module('apiModule')); 
+19

請您分享一個更完整的代碼示例嗎?作爲Angular和Jasmine的新手,我無法繞開這個念頭。 –

+0

@akronym所以你包含'app.js'到測試控制器? – Deeptechtons

+10

但是在測試你的服務時你不會得到同樣的問題嗎? –

6

嘗試實例$resource用下面的代碼:

var $injector = angular.injector(['ng', 'ngResource']); 
var $resource = $injector.get('$resource'); 

其他服務,當他們在其他模塊仍然只是類似。然後將該模塊添加到數組中。

More info

+0

也許我不是在這裏認識的東西。我試過這個,得到了同樣的結果。我更新了我的原始帖子,以包含您的建議。 – akronymn

+0

原來這個解決方案的問題是$資源實際上並不是一項服務。這是一個工廠。 http://docs.angularjs.org/api/ngResource.$resource – akronymn