使用 angularjs 和 jasmine 对客户端进行单元测试时,$scope.alerts 未定义
$scope.alerts undefined when doing unit testing client side with angularjs and jasmine
我正在为我的控制器编写单元测试。我正在用 jasmine 测试 userSave()
函数,并想检查 $scope.alerts
变量的内容,它是一个数组。但是 $scope.alerts
退出 userSave()
函数时是空的,所以我无法检查它的内容。我不知道为什么它是空的,因为 $scope.alerts
是全局的。下面是我的控制器和测试用例的代码。
控制器
'use strict';
angular.module('myApp')
.controller('RegisterCtrl', function ($scope, $http, $location) {
$scope.message = 'Register Route';
$scope.init = function () {
$scope.inviteCode = $location.hash();
};
$scope.init();
$scope.master = {};
// Array to hold alert messages
$scope.alerts = [];
$scope.closeAlert = function (index) {
$scope.alerts.splice(index, 1);
};
$scope.userSave = function (user) {
/*jshint unused: false */
$http.post('api/users/v1/', {
'invite_code': $scope.inviteCode,
'password': user.password,
'last_name': user.lastName,
'first_name': user.firstName
}).success(function (data, status, headers, config) {
$location.url($location.path());
$location.path('/');
}).error(function (data, status, headers, config) {
if (status === 404) {
$scope.alerts.push({
type: 'danger',
msg: 'Your invitation code has expired or is invalid, your registration will require a new one to be completed'
});
} else if (status === 204) {
$scope.alerts.push({
type: 'danger',
msg: 'This email already exists, please click login and forgot your password to recover your password'
});
} else {
$scope.alerts.push({
type: 'danger',
msg: 'There was an error registering'
});
}
});
};
});
测试用例
'use strict';
describe('Controller: RegisterCtrl', function () {
// load the controller's module
beforeEach(module('myApp'));
var RegisterCtrl, scope, httpBackend,http;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, $httpBackend,$http) {
scope = $rootScope.$new();
httpBackend = $httpBackend;
http = $http;
RegisterCtrl = $controller('RegisterCtrl', {
$scope: scope
});
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
it('should return a 404 for expired inviteCode', function () {
var userClientPayload = {
lastName: 'pav',
firstName: 'nga',
password: 'test'
};
var userServerPayload = {
invite_code: 'expiredCode',
last_name: 'pav',
first_name: 'nga',
password: 'test'
};
httpBackend.whenPOST('api/users/v1/',userServerPayload).respond(404);
scope.inviteCode = 'expiredCode';
scope.userSave(userClientPayload);
//httpBackend.expectPOST('api/users/v1/',userServerPayload).respond(404);
console.log(scope.alerts);
expect(scope.alerts.type).toBe('danger');
expect(scope.alerts.msg).toBe('Your invitation code has expired or is invalid, your registration will require a new one to be completed');
httpBackend.flush();
});
});
错误
Controller: RegisterCtrl should return a 404 for expired inviteCode FAILED
Expected undefined to be 'danger'.
at /Users/z001hm0/Documents/api_portal/developer-portal/client/test/unit/controllers/register.controller.spec.js:59
Expected undefined to be 'Your invitation code has expired or is invalid, your registration will require a new one to be completed'.
at /Users/z001hm0/Documents/api_portal/developer-portal/client/test/unit/controllers/register.controller.spec.js:60
$scope.alerts
是一个数组,所以这一行失败 b/c 一个数组没有 type
属性:
expect(scope.alerts.type).toBe('danger');
用下面的内容替换上面的行:
expect(scope.alerts.length).toBe(1);
expect(scope.alerts[0].type).toBe('danger');
编辑
下一个问题是您在调用 httpBackend.flush()
之前调用了 expect()
。对 flush()
的调用使模拟服务器响应在您的测试中发生,这将触发填充 $scope.alerts
.
的代码
因此,如果我们翻转这些代码行,它将如下所示:
httpBackend.flush();
expect(scope.alerts.length).toBe(1);
expect(scope.alerts[0].type).toBe('danger');
我正在为我的控制器编写单元测试。我正在用 jasmine 测试 userSave()
函数,并想检查 $scope.alerts
变量的内容,它是一个数组。但是 $scope.alerts
退出 userSave()
函数时是空的,所以我无法检查它的内容。我不知道为什么它是空的,因为 $scope.alerts
是全局的。下面是我的控制器和测试用例的代码。
控制器
'use strict';
angular.module('myApp')
.controller('RegisterCtrl', function ($scope, $http, $location) {
$scope.message = 'Register Route';
$scope.init = function () {
$scope.inviteCode = $location.hash();
};
$scope.init();
$scope.master = {};
// Array to hold alert messages
$scope.alerts = [];
$scope.closeAlert = function (index) {
$scope.alerts.splice(index, 1);
};
$scope.userSave = function (user) {
/*jshint unused: false */
$http.post('api/users/v1/', {
'invite_code': $scope.inviteCode,
'password': user.password,
'last_name': user.lastName,
'first_name': user.firstName
}).success(function (data, status, headers, config) {
$location.url($location.path());
$location.path('/');
}).error(function (data, status, headers, config) {
if (status === 404) {
$scope.alerts.push({
type: 'danger',
msg: 'Your invitation code has expired or is invalid, your registration will require a new one to be completed'
});
} else if (status === 204) {
$scope.alerts.push({
type: 'danger',
msg: 'This email already exists, please click login and forgot your password to recover your password'
});
} else {
$scope.alerts.push({
type: 'danger',
msg: 'There was an error registering'
});
}
});
};
});
测试用例
'use strict';
describe('Controller: RegisterCtrl', function () {
// load the controller's module
beforeEach(module('myApp'));
var RegisterCtrl, scope, httpBackend,http;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, $httpBackend,$http) {
scope = $rootScope.$new();
httpBackend = $httpBackend;
http = $http;
RegisterCtrl = $controller('RegisterCtrl', {
$scope: scope
});
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
it('should return a 404 for expired inviteCode', function () {
var userClientPayload = {
lastName: 'pav',
firstName: 'nga',
password: 'test'
};
var userServerPayload = {
invite_code: 'expiredCode',
last_name: 'pav',
first_name: 'nga',
password: 'test'
};
httpBackend.whenPOST('api/users/v1/',userServerPayload).respond(404);
scope.inviteCode = 'expiredCode';
scope.userSave(userClientPayload);
//httpBackend.expectPOST('api/users/v1/',userServerPayload).respond(404);
console.log(scope.alerts);
expect(scope.alerts.type).toBe('danger');
expect(scope.alerts.msg).toBe('Your invitation code has expired or is invalid, your registration will require a new one to be completed');
httpBackend.flush();
});
});
错误
Controller: RegisterCtrl should return a 404 for expired inviteCode FAILED
Expected undefined to be 'danger'.
at /Users/z001hm0/Documents/api_portal/developer-portal/client/test/unit/controllers/register.controller.spec.js:59
Expected undefined to be 'Your invitation code has expired or is invalid, your registration will require a new one to be completed'.
at /Users/z001hm0/Documents/api_portal/developer-portal/client/test/unit/controllers/register.controller.spec.js:60
$scope.alerts
是一个数组,所以这一行失败 b/c 一个数组没有 type
属性:
expect(scope.alerts.type).toBe('danger');
用下面的内容替换上面的行:
expect(scope.alerts.length).toBe(1);
expect(scope.alerts[0].type).toBe('danger');
编辑
下一个问题是您在调用 httpBackend.flush()
之前调用了 expect()
。对 flush()
的调用使模拟服务器响应在您的测试中发生,这将触发填充 $scope.alerts
.
因此,如果我们翻转这些代码行,它将如下所示:
httpBackend.flush();
expect(scope.alerts.length).toBe(1);
expect(scope.alerts[0].type).toBe('danger');