使用 Jasmine 对服务进行单元测试 Angular 代码
Unit Testing Angular Code with a Service using Jasmine
我正在尝试测试一个控制器,而不是要求我模拟我用来获取数据的服务。目前我收到一条错误消息,指出此行上的函数未定义:
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');
});
});
这是它的一个小插曲:http://plnkr.co/edit/tBSl88RRhj56h3Oiny6S?p=preview
由于您使用的是 jasmine 2.1,因此 API 是 .and.returnValue
。在您的测试规范中,在 then
之前执行 $scope.$apply()
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');
});
});
这是另一种常见的测试方法 $http
by $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');
});
});
我正在尝试测试一个控制器,而不是要求我模拟我用来获取数据的服务。目前我收到一条错误消息,指出此行上的函数未定义:
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');
});
});
这是它的一个小插曲:http://plnkr.co/edit/tBSl88RRhj56h3Oiny6S?p=preview
由于您使用的是 jasmine 2.1,因此 API 是 .and.returnValue
。在您的测试规范中,在 then
$scope.$apply()
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');
});
});
这是另一种常见的测试方法 $http
by $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');
});
});