I want to be able to turn on and off a $httpBackend mock in my angularJS app.
That means I want to inject the $httpBackend lazily/on demand. It would also be nice to be able to turn it on and off again.
For example to provide input data for an AngularJS app that is being previewed from a CMS.
The below code does only work if I move the ngMockE2E to an ordinary dependency, and inject $httpBackend to my factory the standard way.
The code sets upp $httpBackend on all calls from a config file, and then responds to all of them...
const registerCalls = () => {
const injectormock = angular.injector(['ngMockE2E']); //lazy load not working as expected
const $httpBackend = injectormock.get('$httpBackend'); //lazy load not working as expected.
//Pass through for resources:
$httpBackend.whenGET(/.*.html/).passThrough();
$httpBackend.whenGET(/.*.json/).passThrough();
//API calls should be mocked:
const apiCalls = {};
for (var call in apiConfig) {
if ({}.hasOwnProperty.call(apiConfig, call)) {
const callConfig = apiConfig[call];
const url = angular.isDefined(callConfig.regex) ? callConfig.regex : callConfig.url();
if (callConfig.method === 'GET') {
apiCalls[call] = $httpBackend.whenGET(url);
} else if (callConfig.method === 'POST') {
apiCalls[call] = $httpBackend.whenPOST(url);
}
}
}
return apiCalls;
}
const success = function() {
const apiCalls = registerCalls();
for (var call in apiConfig) {
let response = {};
if (angular.isDefined(apiConfig[call].response)) {
response = apiConfig[call].response();
}
apiCalls[call].respond(200, response);
}
};
How can I setup the $httpBackend so that it can be activated/deactivated while the AngularJS app is running?
Angular services are singletons that are lazily instantiated on first injection. If the injection of
$httpBackend
is performed on application bootstrap (which is usually the case when$http
is used), it's not possible to mock a service.Getting E2E
$httpBackend
version throughangular.injector
is obvious but wrong way to do this. This will result in having new injector instance that uses its own core service singletons ($browser
, etc).The clean way to do this is through
angular.mock.e2e
global, as shown in this example. It will be available once angular-mocks.js is loaded. The point is to decorate$httpBackend
(which is a function) to wrap both original and E2E implementations and use them conditionally.It can be done like that:
Where
mockableHttp
is loaded in app module (can be totally excluded in production) and HTTP mocks are activated with$httpBackend.enableMocking()
.