2

我创建了一个自定义 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 作为参数传递,那就太好了。

4

1 回答 1

4

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

查看 $provide 文档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
        }
    })
}));
于 2013-08-11T13:18:43.170 回答