AngularJs Jasmine Unit test fails with Unexpected Request
Asked Answered
H

1

0

Following is my myService.spec.js :

   'use strict';
    describe('myService', function () {
    var dependentService,dependentService1,rootScope,$q;
    beforeEach(module('myModule.myConfig'));
    beforeEach(module('myModule'));
    beforeEach(inject(function (_myService_, _$rootScope_,
                       _$q_,_dependentService1_,_dependentService_) {
    myService= _myService_;
    rootScope = _$rootScope_.$new();
    $q = _$q_;
    dependentService1= _dependentService1_;
    dependentService= _dependentService_;

    spyOn(dependentService1,'setPath');
    spyOn(dependentService,'get');
    spyOn($q,'all').and.callFake(function(){
        var deferred = _$q_.defer();
        if($q.all.calls.count() === 1){
            deferred.resolve([{path:'./abcd'}]);
        }else if($q.all.calls.count() === 2){
            deferred.resolve([{path:'./abcd','user':  {'userId':'xyz',
                                    'groups':['G1']}}]);
        }else{
            deferred.resolve({});
        }
        return deferred.promise;
    });
}));


it('should load path, information',function(){
    var promise = myService.load();
    rootScope.$apply();
    expect(dependentService.get).toHaveBeenCalled(); 
    expect(dependentService1.setPath).toHaveBeenCalledWith('./abcd');
});

 });

And here is my MyService.js

 'use strict';

 function    myService($q,dependentService1,dependentService){
var appConfigLoaded = false;
function _loadPath(){
    return dependentService.get(dependentService1.url);
}
return {
    load : function(){
        var loadPath = _loadPath(),
         finalDeferred = $q.defer();
         $q.all([loadPath ]).then(function (results) {
            var path = results[0].path ,
            user = results[0].user;
            dependentService1.setPath(path);
         $q.all([_loadDataPromise1(),_loadDataPromise2()]).then(function(results){
                finalDeferred.resolve(results);
            },function(reason){
                finalDeferred.reject(reason);
            });
         },function(reason){
             finalDeferred.reject(reason);
         });
        return finalDeferred.promise;
    }
  };

}
angular.module('myModule.myConfig').service('myService', MyService);

Following functions and service which holds them are omitted for brevity but they return promise. I have spied them as well just like I have spied other two services.

 loadDataPromise1() and loadDataPromise1()  

Now I get some error like Unexpected request GET with URL which points to some headers.template.html. But I am not even making any call to http to get such template nor any of the functions do. which ever call $http.get I have spied them.

I tried with

$httpBackend.flush();

but the same error occur. May be I am doing something basic thing in a wrong way.

If I remove $rootScope.apply() then error goes away. However .then() function in my service attached to first call to $q.all() is not called.

Any pointers to help me out?

Hub answered 26/11, 2015 at 12:18 Comment(0)
F
2

Do you have a default route with a templateURL in your application routing? You are probably running into this issue:
https://github.com/angular/angular.js/issues/2717

The workaround (which is annoying) is to put an expectGET for the templateURL in your beforeEach and then flush it.

$httpBackend.expectGET('path/to/template/defaulttemplate.html').respond(200, '');
$httpBackend.flush();

You can do it anywhere in there - I try and keep it at the top or bottom so it is obvious that is a workaround and not part of the testing code. Note you will have to put those lines in EVERY test file since the routing is part of app (not the module under test).

Flagellant answered 30/11, 2015 at 14:22 Comment(1)
I am using ui-router. Can I just use $httpBackend.flush() before I call $rootScope.apply() without writing any expect* statements? I tried with your solution but then shows up some other request path and throws unexpected request error for that request. Can I just use regex for expect* and return some dummy response for all of them like for all get, post,delete,patch,put type of requests I will return dummy data and then flush() them before calling $rootScope.apply()?Hub

© 2022 - 2024 — McMap. All rights reserved.