Lately I’ve been writing a lot of unit tests in Angular. One of the common needs is to mock services that are not in scope of what’s being tested. One very simple way this can be done is the following:

var promise = {
    then: function () {
    }
};

Let’s say you had a service whose entire point of existence was to mock a real service.

var userMockService = [
    function () {
        var promise = {
            then: function () {
            }
        };

        return {
            addUser: function () {
                return promise;
            },
            deleteUser: function () {
                return promise;
            },
            getUser: function () {
                return promise;
            },
            updateUser: function () {
                return promise;
            }
        };
    }
];

angular.module('myApp', []).factory('userMockService', userMockService);

Then elsewhere you could have code that used that like this:

// Notice the sent argument, which does not
// cause any errors even though the defined
// function does not have a parameter
userMockService.getUser('fred').then(function () {
    // do something
});

If we had an Angular component that required a service called userService, then this mock could be aliased for the real service and sent to a unit test of that component. Using a slightly modified version of Angular’s example, that could look like this:

describe('component: heroDetail', function () {
    var component, scope, hero, $componentController;

    beforeEach(module('heroApp'));

    beforeEach(inject(function ($rootScope, _$componentController_, userMockService) {
        scope = $rootScope.$new();
        $componentController = _$componentController_;
        hero = {name: 'Wolverine'};
    }));

    it('should assign the name bindings to the hero object', function () {
        // Here we are passing actual bindings to the component
        component = $componentController('heroDetail',
            {userService: userMockService},
            {hero: hero}
        );
        expect(component.hero.name).toBe('Wolverine');
    });
});

If you want to take things a step further you can also easily have Sinon spies put on these mocked functions, like so:

var sandbox = sinon.sandbox.create();
var promise = {
    then: sandbox.spy()
};

This way you can check whether a promise-returning async call was ever made or not!

Without getting into any scary APIs you can mock most anything using this technique. The mocks generally look empty and sometimes quite nested in their emptiness. They’re hilarious looking but incredibly useful for testing.