如何对具有多个 $resource 调用的 angular 控制器进行单元测试
How to unit test angular controller having multiple $resource calls
我有一个控制器在初始化时对后端执行多个 $resource 调用。这工作正常,但现在我需要用 jasmine 添加单元测试,问题来了,当我尝试在控制器中保存对象的状态时出现错误。
在控制器初始化时,我进行了 3 次 $resource 调用以填充 3 个下拉菜单,在对 3 个下拉菜单进行选择并在另一个输入文本中输入一个值后,我按下提交(保存)并保存了我的实体。
我对 angular 没有太多经验,所以我真的需要帮助,如果需要其他资源,请尽管提出,我会将它们添加到此 post。谢谢!
现在我需要对这个保存函数进行单元测试,但出现错误:
Chrome 41.0.2272 (Windows 7) permissionController should call the service successfully FAILED
Error: Unexpected request: POST http://localhost:8080/webapp-1.0.0-SNAPSHOT/v1/actions/search
No more request expected
at $httpBackend (C:/_workspace/webapp/Platform/ui/src/main/uidev/node_modules/angular-mocks/angular-mocks.js:1220:9)
at sendReq (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:9628:9)
at serverRequest (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:9344:16)
at processQueue (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:13189:27)
at C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:13205:27
at Scope.$eval (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:14401:28)
at Scope.$digest (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:14217:31)
at Function.$httpBackend.flush (C:/_workspace/webapp/Platform/ui/src/main/uidev/node_modules/angular-mocks/angular-mocks.js:1519:38)
at Object.<anonymous> (C:/_workspace/webapp/Platform/ui/src/main/uidev/test/unit/authz/permission/create-permission-controller-test.js:28:21)
这是控制器:
angular.module('platform.authz').controller('permissionController', function($translatePartialLoader,
PermissionService, ActionService, ResourceService, EnvironmentService, $scope, $state) {
'use strict';
$translatePartialLoader.addPart('authz/permission');
var controller = this;
controller.permission = {};
function errorMessageHandler(response) {
var errorMessages = [];
response.data.messages.forEach(function(message, i) {
errorMessages[i] = {type: 'danger', text: message.description};
});
controller.notificationMessages = errorMessages;
}
controller.populateActions = function() {
ActionService.searchRequestObject().search({search: ''}).$promise.then(function(data) {
controller.actions = data;
}, errorMessageHandler);
};
controller.populateResources = function() {
ResourceService.searchRequestObject().search({search: ''}).$promise.then(function(data) {
controller.resources = data;
}, errorMessageHandler);
};
controller.populateEnvironments = function() {
EnvironmentService.searchRequestObject().search({search: ''}).$promise.then(function(data) {
controller.environments = data;
}, errorMessageHandler);
};
controller.getPermissionSaveRequest = function() {
var permissionSaveRequest = {};
permissionSaveRequest.name = controller.permission.name;
permissionSaveRequest.actionId = controller.permission.action.id;
permissionSaveRequest.resourceId = controller.permission.resource.id;
permissionSaveRequest.environmentId = controller.permission.environment.id;
return permissionSaveRequest;
};
controller.save = function() {
PermissionService.createRequestObject().create(controller.getPermissionSaveRequest()).$promise.then(function() {
controller.notificationMessages = [
{type: 'success', text: 'Save has been successful!'}
];
controller.permission = {};
$scope.permissionDetailsForm.$setPristine();
}, errorMessageHandler);
};
controller.cancel = function cancel() {
$state.reload();
};
controller.actions = controller.populateActions();
controller.resources = controller.populateResources();
controller.environments = controller.populateEnvironments();
});
这是在控制器初始化时调用的服务之一(所有 3 个服务看起来都一样)
angular.module('platform.authz').factory('ActionService', function($resource, $log, configService) {
'use strict';
return {
searchRequestObject: function() {
return $resource(configService.getUrlForService('action') + '/' + 'search', {}, {
search: {method: 'POST', isArray: true}
});
}
};
});
这是我的单元测试试用版:
describe('permissionController', function() {
'use strict';
var httpBackend, permissionController, state, scope;
beforeEach(module('platform'));
beforeEach(inject(function(_$httpBackend_, $controller, _$state_, configService, $rootScope) {
state = _$state_;
spyOn(state, 'go');
spyOn(state, 'transitionTo');
spyOn(configService, 'getUrlForService')
.and.callFake(function(name) {
return CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + name + 's';
}
);
httpBackend = _$httpBackend_;
scope = $rootScope.$new();
permissionController = $controller('permissionController', {$scope: scope});
}));
it('should call the service successfully', function() {
permissionController.permission = {'name': 'all', 'action': {'id': 1, 'name': 'all'}, 'resource': {'id': 1, 'name': 'all'}, 'environment': {'id': 1, 'name': 'all'}};
httpBackend
.whenPOST(CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'permissions', permissionController.getPermissionSaveRequest())
.respond(200, 'created');
permissionController.save();
httpBackend.flush();
expect(permissionController.errorMessages[0].text).toBe('Error');
});
});
问题是您在加载控制器时进行了 3 次 $resource 调用,在执行测试时加载了控制器。所以你应该确保(例如在 beforeEach 中)也模拟那些后端调用。您现在只在按下保存时模拟您期望的那个,但在保存事件之前,您的控制器已经在进行一些后端通信。你得到的例外是告诉你这个:"unexpected request".
修复在这里:
describe('permissionController', function() {
'use strict';
var $httpBackend, permissionController, scope;
beforeEach(module('platform'));
beforeEach(inject(function($injector, _$state_, configService) {
$httpBackend = $injector.get('$httpBackend');
scope = $injector.get('$rootScope').$new();
scope.permissionDetailsForm = {$setPristine: function() {
}};
var state = _$state_;
spyOn(state, 'go');
spyOn(state, 'transitionTo');
spyOn(configService, 'getUrlForService')
.and.callFake(function(name) {
return CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + name + 's';
}
);
var $controller = $injector.get('$controller');
$httpBackend.when('POST', CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'actions/search').respond(200,
'[{"name": "all","id": "1"}]'
);
$httpBackend.when('POST', CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'resources/search').respond(200,
'[{"name": "all","id": "1"}]'
);
$httpBackend.when('POST', CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'environments/search').respond(200,
'[{"name": "all","id": "1"}]'
);
permissionController = $controller('permissionController', {$scope: scope});
$httpBackend.flush();
}));
it('should call the service successfully', function() {
permissionController.permission =
{'name': 'all', 'action': {'id': 1, 'name': 'all'}, 'resource': {'id': 1, 'name': 'all'},
'environment': {'id': 1, 'name': 'all'}};
$httpBackend
.whenPOST(CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'permissions',
permissionController.getPermissionSaveRequest())
.respond(200, 'created');
permissionController.save();
$httpBackend.flush();
expect(permissionController.notificationMessages[0].text).toBe('Save has been successful!');
});
});
我有一个控制器在初始化时对后端执行多个 $resource 调用。这工作正常,但现在我需要用 jasmine 添加单元测试,问题来了,当我尝试在控制器中保存对象的状态时出现错误。
在控制器初始化时,我进行了 3 次 $resource 调用以填充 3 个下拉菜单,在对 3 个下拉菜单进行选择并在另一个输入文本中输入一个值后,我按下提交(保存)并保存了我的实体。
我对 angular 没有太多经验,所以我真的需要帮助,如果需要其他资源,请尽管提出,我会将它们添加到此 post。谢谢!
现在我需要对这个保存函数进行单元测试,但出现错误:
Chrome 41.0.2272 (Windows 7) permissionController should call the service successfully FAILED
Error: Unexpected request: POST http://localhost:8080/webapp-1.0.0-SNAPSHOT/v1/actions/search
No more request expected
at $httpBackend (C:/_workspace/webapp/Platform/ui/src/main/uidev/node_modules/angular-mocks/angular-mocks.js:1220:9)
at sendReq (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:9628:9)
at serverRequest (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:9344:16)
at processQueue (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:13189:27)
at C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:13205:27
at Scope.$eval (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:14401:28)
at Scope.$digest (C:/_workspace/webapp/Platform/ui/src/main/uidev/app/lib/js/angular.js:14217:31)
at Function.$httpBackend.flush (C:/_workspace/webapp/Platform/ui/src/main/uidev/node_modules/angular-mocks/angular-mocks.js:1519:38)
at Object.<anonymous> (C:/_workspace/webapp/Platform/ui/src/main/uidev/test/unit/authz/permission/create-permission-controller-test.js:28:21)
这是控制器:
angular.module('platform.authz').controller('permissionController', function($translatePartialLoader,
PermissionService, ActionService, ResourceService, EnvironmentService, $scope, $state) {
'use strict';
$translatePartialLoader.addPart('authz/permission');
var controller = this;
controller.permission = {};
function errorMessageHandler(response) {
var errorMessages = [];
response.data.messages.forEach(function(message, i) {
errorMessages[i] = {type: 'danger', text: message.description};
});
controller.notificationMessages = errorMessages;
}
controller.populateActions = function() {
ActionService.searchRequestObject().search({search: ''}).$promise.then(function(data) {
controller.actions = data;
}, errorMessageHandler);
};
controller.populateResources = function() {
ResourceService.searchRequestObject().search({search: ''}).$promise.then(function(data) {
controller.resources = data;
}, errorMessageHandler);
};
controller.populateEnvironments = function() {
EnvironmentService.searchRequestObject().search({search: ''}).$promise.then(function(data) {
controller.environments = data;
}, errorMessageHandler);
};
controller.getPermissionSaveRequest = function() {
var permissionSaveRequest = {};
permissionSaveRequest.name = controller.permission.name;
permissionSaveRequest.actionId = controller.permission.action.id;
permissionSaveRequest.resourceId = controller.permission.resource.id;
permissionSaveRequest.environmentId = controller.permission.environment.id;
return permissionSaveRequest;
};
controller.save = function() {
PermissionService.createRequestObject().create(controller.getPermissionSaveRequest()).$promise.then(function() {
controller.notificationMessages = [
{type: 'success', text: 'Save has been successful!'}
];
controller.permission = {};
$scope.permissionDetailsForm.$setPristine();
}, errorMessageHandler);
};
controller.cancel = function cancel() {
$state.reload();
};
controller.actions = controller.populateActions();
controller.resources = controller.populateResources();
controller.environments = controller.populateEnvironments();
});
这是在控制器初始化时调用的服务之一(所有 3 个服务看起来都一样)
angular.module('platform.authz').factory('ActionService', function($resource, $log, configService) {
'use strict';
return {
searchRequestObject: function() {
return $resource(configService.getUrlForService('action') + '/' + 'search', {}, {
search: {method: 'POST', isArray: true}
});
}
};
});
这是我的单元测试试用版:
describe('permissionController', function() {
'use strict';
var httpBackend, permissionController, state, scope;
beforeEach(module('platform'));
beforeEach(inject(function(_$httpBackend_, $controller, _$state_, configService, $rootScope) {
state = _$state_;
spyOn(state, 'go');
spyOn(state, 'transitionTo');
spyOn(configService, 'getUrlForService')
.and.callFake(function(name) {
return CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + name + 's';
}
);
httpBackend = _$httpBackend_;
scope = $rootScope.$new();
permissionController = $controller('permissionController', {$scope: scope});
}));
it('should call the service successfully', function() {
permissionController.permission = {'name': 'all', 'action': {'id': 1, 'name': 'all'}, 'resource': {'id': 1, 'name': 'all'}, 'environment': {'id': 1, 'name': 'all'}};
httpBackend
.whenPOST(CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'permissions', permissionController.getPermissionSaveRequest())
.respond(200, 'created');
permissionController.save();
httpBackend.flush();
expect(permissionController.errorMessages[0].text).toBe('Error');
});
});
问题是您在加载控制器时进行了 3 次 $resource 调用,在执行测试时加载了控制器。所以你应该确保(例如在 beforeEach 中)也模拟那些后端调用。您现在只在按下保存时模拟您期望的那个,但在保存事件之前,您的控制器已经在进行一些后端通信。你得到的例外是告诉你这个:"unexpected request".
修复在这里:
describe('permissionController', function() {
'use strict';
var $httpBackend, permissionController, scope;
beforeEach(module('platform'));
beforeEach(inject(function($injector, _$state_, configService) {
$httpBackend = $injector.get('$httpBackend');
scope = $injector.get('$rootScope').$new();
scope.permissionDetailsForm = {$setPristine: function() {
}};
var state = _$state_;
spyOn(state, 'go');
spyOn(state, 'transitionTo');
spyOn(configService, 'getUrlForService')
.and.callFake(function(name) {
return CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + name + 's';
}
);
var $controller = $injector.get('$controller');
$httpBackend.when('POST', CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'actions/search').respond(200,
'[{"name": "all","id": "1"}]'
);
$httpBackend.when('POST', CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'resources/search').respond(200,
'[{"name": "all","id": "1"}]'
);
$httpBackend.when('POST', CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'environments/search').respond(200,
'[{"name": "all","id": "1"}]'
);
permissionController = $controller('permissionController', {$scope: scope});
$httpBackend.flush();
}));
it('should call the service successfully', function() {
permissionController.permission =
{'name': 'all', 'action': {'id': 1, 'name': 'all'}, 'resource': {'id': 1, 'name': 'all'},
'environment': {'id': 1, 'name': 'all'}};
$httpBackend
.whenPOST(CONFIG.get('MAIN_URL_FOR_REST_SERVICES') + 'permissions',
permissionController.getPermissionSaveRequest())
.respond(200, 'created');
permissionController.save();
$httpBackend.flush();
expect(permissionController.notificationMessages[0].text).toBe('Save has been successful!');
});
});