How do you mock a service in AngularJS when unit testing with jasmine?

KevSheedy picture KevSheedy · Oct 9, 2013 · Viewed 56.7k times · Source

Let's say I have a service shop that depends on two stateful services schedule and warehouse. How do I inject different versions of schedule and warehose into shop for unit testing?

Here's my service:

angular.module('myModule').service('shop', function(schedule, warehouse) {
    return {
        canSellSweets : function(numRequiredSweets){
             return schedule.isShopOpen()
                 && (warehouse.numAvailableSweets() > numRequiredSweets);
        }
    }
});

Here are my mocks:

var mockSchedule = {
    isShopOpen : function() {return true}
}
var mockWarehouse = {
    numAvailableSweets: function(){return 10};
}

Here are my tests:

expect(shop.canSellSweets(5)).toBe(true);
expect(shop.canSellSweets(20)).toBe(false);

Answer

Attila Miklosi picture Attila Miklosi · Oct 9, 2013
beforeEach(function () {
  module(function ($provide) {
    $provide.value('schedule', mockSchedule);
  });
});

Module is a function provided by the angular-mocks module. If you pass in a string argument a module with the corresponding name is loaded and all providers, controllers, services, etc are available for the spec. Generally they are loaded using the inject function. If you pass in a callback function it will be invoked using Angular's $injector service. This service then looks at the arguments passed to the callback function and tries to infer what dependencies should be passed into the callback.