2015-01-20 70 views
0

我試圖測試一個控制器,而不是要求我模擬一個服務,我正在使用獲取數據。目前,我收到一個錯誤說的功能,在這條線未定義:單元測試使用茉莉花服務的角碼

dataServiceMock = jasmine.createSpyObj('dataService', ['getFunctionStuff']); 

根據其它實例,這應該是工作的罰款教程。

這裏是我的代碼,包括測試文件,服務和控制器。

控制器:

var app = angular.module('myApp', []); 

app.controller('MainCtrl', function($scope, dataService) { 

    dataService.getFunctionStuff($scope.foo) 
     .then(function(data) { 
     $scope.test = data; 
     }); 

}); 

服務:

app.factory('dataService', function ($timeout, $q){ 

    function getFunctionStuff(formData) { 
      return $http.post('../randomAPICall', formData).then(function(data) { 
       return data; 
      }); 
     }; 

}); 

測試:

describe('Testing a controller', function() { 
    var $scope, ctrl, $timeout; 

    var dataServiceMock; 

    beforeEach(function(){ 

    dataServiceMock = jasmine.createSpyObj('dataService', ['getFunctionStuff']); 

    module('myApp'); 

    inject(function($rootScope, $controller, $q, _$timeout_) { 

     $scope = $rootScope.$new(); 

     dataServiceMock.getFunctionStuff.and.ReturnValue($q.when('test')); 

     $timeout = _$timeout_; 

     ctrl = $controller('MainCtrl', { 
     $scope: $scope, 
     dataService: dataServiceMock 
     }); 
    }); 
    }); 

    it('should update test', function(){ 
    expect($scope.test).toEqual('test');  
    }); 
}); 

下面是它的一個plunker:http://plnkr.co/edit/tBSl88RRhj56h3Oiny6S?p=preview

+0

我已經發布了2種方法來做單元測試。一種是你創建間諜的方式,另一種是使用'$ httpBackend'這是一種常見的方式。 – elaijuh 2015-01-21 06:17:41

回答

1

當您使用茉莉花2.1時,API是.and.returnValue。並在測試規範,前then

describe('Testing a controller', function() { 
    var $scope, ctrl, $timeout; 

    var dataServiceMock; 

    beforeEach(function() { 

     dataServiceMock = jasmine.createSpyObj('dataService', ['getFunctionStuff']); 

     module('myApp'); 

     inject(function ($rootScope, $controller, $q, _$timeout_) { 

      $scope = $rootScope.$new(); 

      dataServiceMock.getFunctionStuff.and.returnValue($q.when('test')); 

      $timeout = _$timeout_; 

      ctrl = $controller('MainCtrl', { 
       $scope: $scope, 
       dataService: dataServiceMock 
      }); 
     }); 
    }); 

    it('should update test', function() { 
     $scope.$apply(); 
     expect($scope.test).toEqual('test'); 
    }); 
}); 
+0

你能解釋爲什麼我需要使用$ scope。$ apply()?我嘗試過它,它的工作很棒,我只是想明白。 – Blake 2015-01-21 16:47:15

+0

@Blake - 您需要使用$ apply()將承諾解析傳播給'then'函數。參考[angular $ q document](https://docs.angularjs.org/api/ng/service/$q) – elaijuh 2015-01-22 02:08:27

0

這裏做$scope.$apply()是測試$http$httpBackend另一種常見的方式:

app.js

var app = angular.module('myApp', []); 

app.controller('MainCtrl', function($scope, dataService) { 

    dataService.getFunctionStuff($scope.foo) 
     .then(function(data) { 
     $scope.test = data.data; 
     }); 

}); 

dataService.js

app.factory('dataService', function($http) { 

    function getFunctionStuff(formData) { 
    return $http.post('../randomAPICall', formData).then(function(data) { 
     return data; 
    }); 
    } 

    return { 
    getFunctionStuff: getFunctionStuff 
    }; 

}); 

specs.js

describe('Testing a controller', function() { 
    var $scope, ctrl, $controller, $httpBackend; 

    beforeEach(function(){ 

    module('myApp'); 

    inject(function($injector) { 

     $httpBackend = $injector.get('$httpBackend'); 
     $scope = $injector.get('$rootScope').$new(); 
     $controller = $injector.get('$controller'); 

     $scope.foo = 'foo'; 
     $httpBackend.expectPOST('../randomAPICall', 'foo').respond(201, 'test'); 
     ctrl = $controller('MainCtrl', {$scope: $scope}); 
    }); 

    }); 

    it('should update test', function(){ 
    expect($scope.test).not.toBeDefined(); 
    $httpBackend.flush(); 
    expect($scope.test).toEqual('test');  
    }); 
});