Mocking $http calls using $httpBackend

Loading

In AngularJS, $http is commonly used for making API calls. When testing, it’s crucial to mock HTTP requests to prevent actual API calls. AngularJS provides $httpBackend to intercept and mock $http calls.

This guide covers:

  1. What is $httpBackend?
  2. Setting Up Karma and Jasmine for Testing
  3. Mocking GET Requests
  4. Mocking POST Requests
  5. Handling Errors and Edge Cases
  6. Best Practices
  7. Running Tests

1. What is $httpBackend?

$httpBackend is an AngularJS service that intercepts $http calls and allows us to: ✔ Mock API responses.
✔ Simulate success and failure scenarios.
✔ Test API-dependent components without calling real servers.


2. Setting Up Karma and Jasmine

Ensure you have Karma and Jasmine installed:

npm install karma karma-jasmine jasmine-core karma-chrome-launcher angular-mocks --save-dev

In karma.conf.js, include angular-mocks:

files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app.js',
'services/*.js',
'controllers/*.js',
'tests/**/*.spec.js'
]

3. Mocking GET Requests

Example: UserService (userService.js)

app.service('UserService', function($http) {
this.getUser = function() {
return $http.get('/api/user');
};
});

Test Case for GET Request (userService.spec.js)

describe('UserService', function() {
var UserService, $httpBackend;

beforeEach(module('myApp'));

beforeEach(inject(function(_UserService_, _$httpBackend_) {
UserService = _UserService_;
$httpBackend = _$httpBackend_;
}));

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

it('should fetch user data successfully', function() {
var mockUser = { id: 1, name: "John Doe" };

$httpBackend.expectGET('/api/user').respond(200, mockUser);

var result;
UserService.getUser().then(function(response) {
result = response.data;
});

$httpBackend.flush(); // Triggers the mock response

expect(result).toEqual(mockUser);
});
});

Explanation:

  • $httpBackend.expectGET('/api/user').respond(200, mockUser); → Mocks GET request.
  • $httpBackend.flush(); → Triggers the response.
  • expect(result).toEqual(mockUser); → Ensures response data matches mock.

4. Mocking POST Requests

Example: Authentication Service (authService.js)

app.service('AuthService', function($http) {
this.login = function(credentials) {
return $http.post('/api/login', credentials);
};
});

Test Case for POST Request (authService.spec.js)

describe('AuthService', function() {
var AuthService, $httpBackend;

beforeEach(module('myApp'));

beforeEach(inject(function(_AuthService_, _$httpBackend_) {
AuthService = _AuthService_;
$httpBackend = _$httpBackend_;
}));

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

it('should authenticate user successfully', function() {
var credentials = { username: "admin", password: "password" };
var mockResponse = { token: "abcd1234" };

$httpBackend.expectPOST('/api/login', credentials).respond(200, mockResponse);

var result;
AuthService.login(credentials).then(function(response) {
result = response.data;
});

$httpBackend.flush(); // Simulates response

expect(result).toEqual(mockResponse);
});
});

Key Points:

  • $httpBackend.expectPOST('/api/login', credentials).respond(200, mockResponse); → Mocks POST request.
  • Ensures correct request body and response.
  • Uses $httpBackend.flush() to trigger the response.

5. Handling Errors and Edge Cases

To test error handling, modify the AuthService:

app.service('AuthService', function($http) {
this.login = function(credentials) {
return $http.post('/api/login', credentials)
.catch(function(error) {
return error;
});
};
});

Test Case for Failed Authentication

it('should handle authentication failure', function() {
var credentials = { username: "admin", password: "wrongpass" };
var mockError = { message: "Invalid Credentials" };

$httpBackend.expectPOST('/api/login', credentials).respond(401, mockError);

var result;
AuthService.login(credentials).then(function(response) {
result = response;
});

$httpBackend.flush();

expect(result.status).toBe(401);
expect(result.data).toEqual(mockError);
});

Handling Network Errors

it('should handle network error', function() {
$httpBackend.expectGET('/api/user').respond(-1); // Simulating network failure

var result;
UserService.getUser().catch(function(error) {
result = error;
});

$httpBackend.flush();

expect(result.status).toBe(-1);
});

6. Best Practices

Use verifyNoOutstandingExpectation() and verifyNoOutstandingRequest() to clean up mock requests.
Always call $httpBackend.flush() to trigger responses.
Use respond(-1) to simulate network failures.
Keep tests isolated. Each test should work independently.
Use .catch() in service methods to handle HTTP errors gracefully.

Leave a Reply

Your email address will not be published. Required fields are marked *