Check out myAngular article series with live demos and Facebook group Angular - Advanced Topics

How to mock providers in Angular

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Sun May 10 2015

Providers in Angular serve as a way to create independent components that can be injected into other components. There are several different types of providers; service, factory, value, constant and provider, but the idea is very similar between all of them.

In this post I will demonstrate how to mock the different types through Angular dependency injection.

Below are simple examples of the different provider types. The actual implementation of the getCustomerById method is omitted for brevity.

angular.module('app').factory('customerFactory', function(){
    return {getCustomerById:getCustomerById};
    function getCustomerById(id){
        //Add implementation
    }
});

angular.module('app').service('customerService',function() {
    this.getCustomerById = function (id) {
        //Add implementation
    };
});

angular.module('app').value('customerValue', {'name' : 'Joe Smith'});

angular.module('app').constant('customerConstant', {'industry' : 'retail'});

angular.module('app').provider('customerProvider', function(){
    return {
        $get: function (id) {
            return {
                getCustomerById: function(){
                    //Add implementation
                }
            }
        }
    }
});

angular.module('app').controller('customerController',
    ['customerFactory',
    'customerService',
    'customerValue',
    'customerConstant',
    'customerProvider',
    '$scope',
    function(factory,service,value,constant,provider,$scope){
        $scope.fromFactory = factory.getCustomerById(1);
        $scope.fromService = service.getCustomerById(1);
        $scope.fromProvider = provider.getCustomerById(1);
        $scope.value = value.name;
        $scope.constant = constant.industry;
    }
]);

I have also included a sample controller for injecting the providers. The point of this exercise is to show how to hijack the dependency injection and insert mock implementations of the providers.

In the following test I will show how to wire up mocking of these providers and bypass the original implementations.

describe('ProviderTests', function(){
    var $controller;
    var $scope;

    //service
    function customerServiceMock(){}
    customerServiceMock.prototype.getCustomerById = function(id){return 'mockCustomerFromService';};
   
    //factory
    var customerFactoryMock = {};
    customerFactoryMock.getCustomerById = function(id){return 'mockCustomerFromFactory';};

    //provider
    var customerProviderMock = {$get:function(){return {getCustomerById: 
    function(id){return "mockProviderFactory"}}}};
    
    //value
    var customerValue = {'name' : 'Jim Test'};
   
    //constant
    var customerConstant =  {'industry' : 'IT'};

    //override injected value in controller
    beforeEach(module('app', function($provide) {
        $provide.service('customerService', customerServiceMock);
        $provide.factory('customerFactory', function(){return customerFactoryMock;});
        $provide.provider('customerProvider', function(){return customerProviderMock});
        $provide.value('customerValue', customerValue);
        $provide.constant('customerConstant', customerConstant);
    }));

    beforeEach(function(){
        inject(function ($injector){
            $controller = $injector.get('$controller');
            $scope = $injector.get('$rootScope').$new();
        });
    });

    it('should use mocked providers', function(){
        $controller('customerController',{$scope:$scope});
        expect($scope.fromFactory).toBe('mockCustomerFromFactory');
        expect($scope.fromService).toBe('mockCustomerFromService');
        expect($scope.fromProvider).toBe('mockProviderFactory');
        expect($scope.value).toBe('Jim Test');
        expect($scope.constant).toBe('IT');
    });
});

As you can see above, the key is to use the $provide service to register mock providers that will be injected when requested by the controller.

If you liked this article, share it with your friends on social media:

We also have a new Facebook group about advanced Angular topics.

I invite you to follow me on twitter