I'm developing an angular WebApp and since the BackEnd is not still ready I'm using a fake backend ( $httpBackend
) to test my REST request.
It is defined in app.js in this way:
// we want to use $httpBackend mock
app.config(function($provide) {
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
});
// define our fake backend
app.run(function($http, $httpBackend, url) {
//Escape string to be able to use it in a regular expression
function regEsc(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
// Mocking the login request
//define the success var
var user = {username: "me@stuff.it", password: "pass"};
var userResponse = {
"succes": "true",
"user":{
"id":"8490394",
"username": "me",
"token": "asd8u09u900asduijjaijjHJ"
}
};
//success case
$httpBackend.whenPOST(url.login, user).respond(200,userResponse);
//other cases
$httpBackend.whenPOST(url.login).respond(403,{success: false, message: 'Wrong username or password'});
//let pass all views request
$httpBackend.whenGET(function(string){
console.log(string);
return true;
}).passThrough();
$httpBackend.whenGET( RegExp( regEsc( "views/" ) ) ).passThrough();
});
And it works properly when I run the Application with grunt serve
The problems begin when I try to run the test I worte (in Jasmine and executed trough Karma), here it is a sample test:
'use strict';
describe('Service: Loginservice', function () {
// load the service's module
beforeEach(module('cmmApp'));
// instantiate service
var Loginservice, $rootScope, $httpBackend, url;
beforeEach(inject(function (_Loginservice_, _$rootScope_ , $injector, _url_) {
Loginservice = _Loginservice_;
$rootScope = _$rootScope_;
url = _url_;
//questo serve per iniettare httpBackend
$httpBackend = $injector.get('$httpBackend');
$httpBackend.when('POST', url.login, {username: "me@stuff.it",password:"pass"}).respond({success: true, user:{"id":"8490394","username": "me","token": "asd8u09u900asduijjaijjHJ"}});
$httpBackend.whenPOST(url.login).respond(403, {success: false, message: 'Wrong username or password'});
}));
it('should return user object', function () {
var f;
//se i valori sono corretti ritona un oggetto che contiene l'utente
inject(function(Loginservice, $rootScope){
Loginservice.login({username:"me@stuff.it",password:"pass"}).then(function(res){
f = res;
}); //end login
//this trigger the promise
$rootScope.$digest();
//this trigger the http request
$httpBackend.flush();
expect(f).toEqual({success: true, user:{"id":"8490394","username": "me","token": "asd8u09u900asduijjaijjHJ"}});
}); //end inject
});
They work perfectly if I remove the fake backend config from app.js, instead if I leave it there Karma report: Error: No pending request to flush !
I think that this is beacause of the interceptors declared in app.js are triggered and prevent the $httpBackend defined in the test to be triggered on a request.
Any idea on how to solve this issue?
Thanks in advance
ngMockE2E will make your httpBackend useless in unit tests. I struggled with the same thing. I have now been putting all my mock objects in a module, my.mocks
or whatever, and then using that in e2e tests as well as in unit tests.
For e2e testing and backendless development, I have an appDev
module that gets bootstrapped and requires the app
module, the my.mocks
module, and the ngMockE2E
module.
For unit testing I load app
and the mocks then do basically the same when()'s as my appDev code, it really does seem silly to me to duplicate things but at the same time I often want to test using data that will throw an error and I find myself with some custom unit test responses aside from the e2e responses.
$httpBackend
won't make your life easy, and it is very much angular-centric, meaning that any XHR in your app not done through Angular won't return the fake data you defined.
Another alternative is to monkey-patch XMLHttpRequest
to intercept calls to the service you want to simulate, and pass them to a pseudo-RESTful service running on the client side. That's exactly what FakeRest does, so you might want to take a look at it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.