Angular and Jasmine HTTP mocking

This took me an embarrassingly long time to figure out. I spent a good few hours working this out. I was originally trying to inject the service I was trying to create tests for directly into the test function and then mock the $http before all of that. I was trying something like this:

describe('user', function () {
    beforeEach(module('ibexApp'));

    beforeEach(inject(function ($injector) {
        $httpBackend = $injector.get('$httpBackend');
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it('should return false from the HTTP call to get the user', inject(function (User, $httpBackend) {
        $httpBackend.expectGET('api/auth/user').respond({key: 'val'});
        User.get().then(function (response) {
            expect(response).toEqual({key: 'val'});
        });
        $httpBackend.flush(); //needed to resolve and handle promise returned by $http
    });
});

But this didn’t work as it wasn’t injecting the $httpBackend!

So the correct code is:

describe('user', function () {
    beforeEach(module('ibexApp'));

    var service, $httpBackend;

    beforeEach(inject(function ($injector) {
        service = $injector.get('User');
        $httpBackend = $injector.get('$httpBackend');
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it ('should return false from the HTTP call to get the user', function () {
        $httpBackend.when('GET', 'api/auth/user').respond(false);
        service.get().then(function (response) {
            expect(response).toEqual(false);
        });
        $httpBackend.flush(); // waits until the promise has completed
    });
});

On a note of mocking failing HTTP requests, just change the $httpBackend.when to return a different response code like so:

$httpBackend.when(‘GET’, ‘api/auth/user’).respond(400, {success: false});