如何对具有多个$resource调用的角度控制器进行单元测试

How to unit test angular controller having multiple $resource calls

本文关键字:控制器 单元测试 调用 resource      更新时间:2023-09-26

我有一个控制器,它在初始化时对后端执行多个$resource调用。这很好,但现在我需要使用jasmine添加单元测试,问题来了,当我试图在控制器中保存对象的状态时,我遇到了一个错误。

在控制器初始化时,我调用3$resource来填充3个下拉列表,在对3个下拉菜单进行选择并在另一个输入文本中输入值后,我按下submit(保存),我的实体就被保存了。

我在angular方面没有太多经验,所以我真的需要帮助,如果需要其他资源,只要问一下,我就会把它们添加到这个帖子中。谢谢

现在我需要对这个保存功能进行单元测试,我得到了一个错误:

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中)也模拟那些后端调用。当按下save时,您现在只是在嘲笑您所期望的,但在save事件之前,您的控制器已经在进行一些后端通信。您得到的异常告诉您:"意外请求"。

修复程序在这里:

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!');
});
});