AngularJS覆盖使用jasmine进行单元测试的服务的资源依赖性

时间:2013-08-08 22:19:06

标签: angularjs dependency-injection jasmine karma-runner

我创建了一个自定义ngResource,它将API_END_POINT添加到url中。这到目前为止工作正常。但对于单元测试,我想用标准ngResource覆盖customResource。以下代码有效但在调用service = $ injector.get('svcSecurity')后如何覆盖customResource依赖项?

服务:

angular.module('common.security.service', ['common.resource'])

.factory('svcSecurity', ['customResource', function($resource) { 
    var service = {
        // Attempt to authenticate a user by the given email and password
        login: function(email, password) {
            return $resource('/login').save({}, {email: email, password: password}, function(response){
                alert(response.success);
            }, function(ex) {
                alert("exception");
            });
        },       
    };
    return service;
}]);

资源:

angular.module('common.resource', ['common.configuration', 'ngResource'])

// http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/

.factory('customResource', ['$resource', 'API_END_POINT', function($resource, API_END_POINT) {
    return function(url, params, methods) {
        // prepend API_END_POINT to url
        var resource = $resource(API_END_POINT + url, params, methods);
        //var resource = $resource(url, params, methods);

        return resource;
    };
}]);

单元测试:

describe('common.security.service', function() {
    beforeEach(module('common.security.service'));

    beforeEach(inject(function($injector) {
        $httpBackend = $injector.get('$httpBackend');   
        $rootScope = $injector.get('$rootScope');        
        service = $injector.get('svcSecurity');
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });    

    describe('login', function() {
        it('sends a http request to login the specified user', function() {          
            $httpBackend.when('POST', 'http://localhost/api/login').respond(200, {success: 'true'});
            $httpBackend.expect('POST', 'http://localhost/api/login');
            service.login('email', 'password');
            $httpBackend.flush();
        });
    });
});

基于http://docs.angularjs.org/api/ngMock.$httpBackend,控制器可以像这样实例化:

beforeEach(inject(function($injector) {
 // Set up the mock http service responses
 $httpBackend = $injector.get('$httpBackend');
 // backend definition common for all tests
 $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});

 // Get hold of a scope (i.e. the root scope)
 $rootScope = $injector.get('$rootScope');
 // The $controller service is used to create instances of controllers
 var $controller = $injector.get('$controller');

 createController = function() {
   return $controller('MyController', {'$scope' : $rootScope });
 };
}));

如果我可以使用我的服务执行此操作并将ngResource作为参数传递,那将会很棒。

1 个答案:

答案 0 :(得分:3)

您可以注册其他提供商来测试服务

查看$ offer文档http://docs.angularjs.org/api/AUTO.$provide

使用自己的其他服务模拟很有用。通过这样做,您可以独立于其他依赖项测试您的服务。

在测试中,您可以通过将函数作为第二个参数传递给模块函数并在那里设置模拟来实现,在您的情况下,它将是$ resource服务。

beforeEach(module('common.security.service', function($provide) {
    $provide.provide('svcSecurity', function() {
        this.$get = function($resource) {
            return $resource
        }
    })
}));