How can i inject a mock service into a unit test for a filter?

angularjs, javascript, mocking, unit-testing

Solution

Ok, figured this out thanks largely to this answer.

The trick was to simply override the factory provider of the service, by using angular-mocks.js model function in a before each (angular just takes the last defined factory it would seem)

beforeEach(module(function($provide) {
  $provide.factory('User', function() {
    var getSync;
    getById = function(id) {
      return {
        firstName: 'Bob'
      };
    };
    return {
      getById: getById
    };
  });
}));

I suspect that I'll need to be careful with teardown between tests, but the injection into the filter now works fine.

Problem

I have a simple angularjs filter (it takes an id and converts it to a name string), that depends on a custom service to do its work: ``` angular.module('app').filter('idToName', function(User) { return function(id) { var result, user; result = ''; if (id) { result = 'no name found'; user = User.getById(id); if (user) { result = user.firstName; } } return result; }; } ); ``` and I want to write a unit test for it. I would like to be able to inject a mock of the User service into the test. I can do this for a controller unit test as shown in the documentation: ``` var mockUserService; mockUserService = { getById: function(id) { return { firstName: 'Bob' }; } }; beforeEach(inject(function($rootScope, $controller) { var ctrl, scope, userService; userService = mockUserService; scope = $rootScope.$new(); return ctrl = $controller('someController', { $scope: scope, User: userService }); })); ``` but replacing $controller with $filter in the beforeEach does not work, as I presume filters are constructed differently by angular (i.e. don't allow you to inject locals as a second parameter to the constructor.) Has anyone come across this / solved this before?

Original source