When mocking HTTP requests using $httpBackend
in AngularJS unit tests fails, it’s typically due to incorrect setup, improper expectations, or a mismatch between the mocked URL and the one used in the code under test. Let’s break this issue down step by step, explain the common pitfalls, and walk through a working example.
What is $httpBackend
?
$httpBackend
is a mock HTTP backend service provided by angular-mocks.js
, used for unit testing services, controllers, or components that make $http
requests without making actual network calls.
Common Issues When $httpBackend
Doesn’t Work
1. angular-mocks.js
Not Included
If angular-mocks.js
is not loaded, $httpBackend
will be undefined.
Fix: In karma.conf.js
, ensure:
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
...
]
2. Wrong Module Initialization
Always load your module and any dependencies before injecting $httpBackend
.
Fix:
beforeEach(module('myApp'));
3. $httpBackend Expectations Not Matching the Actual Request
Mismatch in method, URL, or payload will cause the test to fail silently or unexpectedly.
Example: If your code calls:
$http.post('/api/data', { id: 1 });
But you mock:
$httpBackend.expectGET('/api/data');
It won’t match, and your test will hang or throw.
4. Forgot to Call $httpBackend.flush()
After making a request in your test, you must call .flush()
to simulate the server’s response.
$httpBackend.flush();
Without it, the test won’t resolve the promise and may timeout.
5. $httpBackend Not Injected Properly
Make sure $httpBackend
is injected in the test:
beforeEach(inject(function(_$httpBackend_, _myService_) {
$httpBackend = _$httpBackend_;
myService = _myService_;
}));
Underscores are a naming convention to avoid naming conflicts and let Angular inject the right dependency.
6. Request Made in the Wrong Digest Cycle
Sometimes the test doesn’t trigger a digest cycle or you need to wrap your test inside a $apply()
.
Working Example of a $httpBackend
Unit Test
1. Service to Test
angular.module('myApp', [])
.service('DataService', function($http) {
this.getData = function() {
return $http.get('/api/data');
};
});
2. Unit Test
describe('DataService', function() {
var DataService, $httpBackend;
beforeEach(module('myApp'));
beforeEach(inject(function(_DataService_, _$httpBackend_) {
DataService = _DataService_;
$httpBackend = _$httpBackend_;
}));
it('should fetch data from API', function() {
var mockResponse = { message: 'Success' };
// Set expectation
$httpBackend.expectGET('/api/data').respond(200, mockResponse);
var result;
DataService.getData().then(function(res) {
result = res.data;
});
// Flush pending requests
$httpBackend.flush();
expect(result).toEqual(mockResponse);
});
afterEach(function() {
// Ensure all requests were made
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
});
Additional Tips
1. Test POST Requests
$httpBackend.expectPOST('/api/data', { name: 'John' }).respond(201, { status: 'Created' });
2. Mocking Multiple Endpoints
$httpBackend.expectGET('/api/user').respond(200, { name: 'Alice' });
$httpBackend.expectGET('/api/messages').respond(200, []);
3. Catch-All Fallback (Not Recommended for Strict Testing)
$httpBackend.whenGET(/.*/).respond(200, {});
Cleanup: verifyNoOutstandingRequest
and verifyNoOutstandingExpectation
This ensures you’ve called flush()
for all mocked requests and set all expectations properly:
afterEach(function() {
$httpBackend.verifyNoOutstandingRequest();
$httpBackend.verifyNoOutstandingExpectation();
});
Summary Checklist
Check | ✔️ Status |
---|---|
angular-mocks.js included | ✅ |
Module loaded with beforeEach(module('...')) | ✅ |
$httpBackend and service injected properly | ✅ |
Correct method and URL used in expect...() | ✅ |
flush() called to simulate server response | ✅ |
verifyNoOutstandingRequest() used for cleanup | ✅ |
Tags
angularjs, $httpBackend, unit testing, angular-mocks, mocking http, jasmine, karma, angularjs testing, mock backend, http testing, $http, test setup, angular service testing, asynchronous testing, javascript unit tests, karma configuration, dependency injection, angular mocks, jasmine unit test