In AngularJS unit testing, $httpBackend is used to mock HTTP requests made by services. However, sometimes $httpBackend fails to intercept requests, causing tests to fail unexpectedly.
Common Symptoms
- The test times out without completing.
- The request is never intercepted, and no response is returned.
$httpBackend.flush()throws an error: vbnetCopyEditError: No pending request to flush
This guide will walk through why $httpBackend fails to intercept requests and how to fix these issues.
1. Why $httpBackend Fails to Intercept Requests?
✅ 1.1. $httpBackend.whenGET() Does Not Match the Request
$httpBackend can only intercept a request if the URL exactly matches the pattern provided in .whenGET() or .expectGET().
Incorrect Matching Example:
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
myService.getData(); // This makes a request to '/api/data?user=123'
$httpBackend.flush(); // Fails: No matching request found!
Why This Fails:
- If
myService.getData()makes a request to/api/data?user=123, it does not match/api/data.
Fix: Use Regex or Wildcards
$httpBackend.whenGET(/\/api\/data.*/).respond(200, { value: 100 });
Or Allow Any Query Params:
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
1.2. $httpBackend is Defined After the Request is Made
If the service makes the request before $httpBackend.whenGET() is defined, the request is not intercepted.
Incorrect Order:
myService.getData(); // HTTP request happens before $httpBackend is set
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
$httpBackend.flush(); // No pending request to flush
Fix: Define $httpBackend Before Calling the Service
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
myService.getData(); // Now the request happens after interception is set
$httpBackend.flush();
1.3. Using $httpBackend.expectGET() but Not Calling the Request
.expectGET() requires the test to call the exact request; otherwise, the test will fail.
Incorrect Example:
$httpBackend.expectGET('/api/data').respond(200, { value: 100 });
// The test never calls myService.getData(), so this will fail
$httpBackend.flush();
Fix: Ensure the Request is Triggered
$httpBackend.expectGET('/api/data').respond(200, { value: 100 });
myService.getData(); // Now the request is made
$httpBackend.flush();
Alternative Fix: Use .whenGET() Instead of .expectGET()
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
// No need to explicitly call myService.getData()
1.4. $httpBackend.flush() Is Not Called
$httpBackend.flush(); is required to trigger the response manually.
Without Flushing:
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
myService.getData(); // This makes the request, but no response is sent
Fix: Flush the Requests
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
myService.getData();
$httpBackend.flush(); // Now the response is returned
1.5. $httpBackend Not Injected Properly
$httpBackend must be injected inside a test case to work properly.
Incorrect Injection:
describe('MyService', function () {
var myService;
beforeEach(module('myApp'));
beforeEach(inject(function (_myService_) {
myService = _myService_;
}));
it('should get data from API', function () {
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
myService.getData();
$httpBackend.flush(); // Throws error because $httpBackend is undefined
});
});
Fix: Inject $httpBackend in beforeEach()
describe('MyService', function () {
var myService, $httpBackend;
beforeEach(module('myApp'));
beforeEach(inject(function (_myService_, _$httpBackend_) {
myService = _myService_;
$httpBackend = _$httpBackend_; // Properly injected
}));
it('should get data from API', function () {
$httpBackend.whenGET('/api/data').respond(200, { value: 100 });
myService.getData();
$httpBackend.flush(); // Works fine now
});
});
1.6. $httpBackend.verifyNoOutstandingExpectation() Fails
If $httpBackend.verifyNoOutstandingExpectation() fails, it means there are unmatched expectGET() calls.
Incorrect Example:
$httpBackend.expectGET('/api/data').respond(200, { value: 100 });
// myService.getData() is never called
$httpBackend.flush();
$httpBackend.verifyNoOutstandingExpectation(); // Error: Unsatisfied request
Fix: Ensure All Expected Requests Are Made
$httpBackend.expectGET('/api/data').respond(200, { value: 100 });
myService.getData(); // Request is made
$httpBackend.flush();
$httpBackend.verifyNoOutstandingExpectation(); // Passes
2. Summary of Fixes
| Issue | Solution |
|---|---|
$httpBackend.whenGET() doesn’t match request | Use regex or wildcard /\/api\/data.*/ |
$httpBackend defined after request is made | Define $httpBackend.whenGET() before service call |
.expectGET() used but request never made | Ensure the service call happens |
$httpBackend.flush() not called | Always call $httpBackend.flush(); after the request |
$httpBackend not injected properly | Inject $httpBackend in beforeEach() |
verifyNoOutstandingExpectation() fails | Ensure all expected requests are made |
