Mocking AngularJS Promises in Unit Tests

Shows how to use $q service to mock services that return promises in unit tests.

HTML

<script src="http://code.angularjs.org/1.1.0/angular.js"></script>
<script src="https://raw.github.com/pivotal/jasmine/master/lib/jasmine-core/jasmine.js"></script>
<script src="https://raw.github.com/pivotal/jasmine/master/lib/jasmine-core/jasmine-html.js"></script>
<script src="http://code.angularjs.org/1.1.0/angular-mocks.js"></script>
<link rel="stylesheet" href="http://tryjasmine.com/js/vendor/jasmine-1.1.0/jasmine.css">

JavaScript

function PeopleListController($scope, people) {
    $scope.peopleList = [];

    $scope.init = function() {
        people.requestPeople().then(function() {
            $scope.peopleList = people.peopleStore;
        });
    };
}

describe('People List Controller', function() {
    var scope;
    var peopleService;
    var controller;
    var q;
    var deferred;

    // define the mock people service
    beforeEach(function() {
        peopleService = {
            peopleStore: [{
                FirstName: "Jim",
                LastName: "Lavin",
                Email: "[email protected]",
                Bio: "Creator and Host of Coding Smackdown TV"}],

            requestPeople: function() {
                deferred = q.defer();
                return deferred.promise;
            }
        };
    });

    // inject the required services and instantiate the controller
    beforeEach(inject(function($rootScope, $controller, $q) {
        scope = $rootScope.$new();
        q = $q;
        controller = $controller(PeopleListController, {
            $scope: scope,
            people: peopleService
        });
    }));

    it('should call requestPeople on the people service when init is called',

    function() {
        spyOn(peopleService, 'requestPeople').andCallThrough();

        scope.init();

        deferred.resolve();

        scope.$root.$digest();

        expect(peopleService.requestPeople).toHaveBeenCalled();
    });

    it('should populate the peopleList when init is called',

    function() {
        scope.init();

        deferred.resolve();

        scope.$root.$digest();

        expect(scope.peopleList).not.toBe([]);
    });
});

(function() {
    var jasmineEnv = jasmine.getEnv();
    jasmineEnv.updateInterval = 1000;

    var trivialReporter = new jasmine.TrivialReporter();
    jasmineEnv.addReporter(trivialReporter);

    jasmineEnv.specFilter = function(spec) {
        return trivialReporter.specFilter(spec);
    };

    $(function()...