Mocking $httpBackend - how to handle "Unexpected request, No more request expected"?

57,989

Solution 1

Your test fails because a request is made which you haven't specified.

Try to add:

$httpBackend.when('GET', 'views/core/main/main.html').respond(fakedMainResponse);

Of course you should also define fakedMainResponse.

Please take a look also at the documentation (section Request Expectations vs Backend Definitions) which says:

Request expectations provide a way to make assertions about requests made by the application and to define responses for those requests. The test will fail if the expected requests are not made or they are made in the wrong order.

The second paramete of $httpBackend.when is actually a RegExp. So if you provide a RegExp that will match all other requests it should work.

Solution 2

For those who are using the httpBackend to mock http calls in EndToEnd tests or just mocking the entire http calls for the application the solution is to add the following code in the app config section (change the regexp according your template's location):

$httpBackend.whenGET(/^\/templates\//).passThrough();

Reference: https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend

Tested with angularjs 1.4 to fix similar problem while integrating ui-router

Solution 3

I think it's also important to notice that if you have a $digest(), your expectation should follow the $digest, like so:

_$rootScope_.$digest();
$httpBackend.when('GET', 'views/core/main/main.html').respond(fakedMainResponse);
// ...
$httpBackend.flush(); // And remember to flush at the end
Share:
57,989
onkami
Author by

onkami

Just a furry.

Updated on October 27, 2021

Comments

  • onkami
    onkami over 2 years

    I have a Jasmine test that is coded like this:

      it ("should send correct message to server to get data, and correctly set up scope when receiving it", function(){
        $httpBackend.when('GET', 'https://localhost:44300/api/projectconfiguration/12').respond(fakedDtoBase);
        $routeParams.projectId=fakeId; // user asks for editing project
        scope.$apply(function(){
            var controller=controllerToTest(); // so controller gets data when it is created
        });
        expect(scope.projectData).toEqual(fakedDtoBase);
    });
    

    and it kind of works, but I get the error:

    Error: Unexpected request: GET views/core/main/main.html
    No more request expected
        at $httpBackend (C:/SVN/src/ClientApp/client/bower_components/angular-mocks/angular-mocks.js:1207:9)
        at sendReq (C:/SVN/src/ClientApp/client/bower_components/angular/angular.js:7800:9)
        at $http.serverRequest (C:/SVN/src/ClientApp/client/bower_components/angular/angular.js:7534:16)
        (more stack trace)....
    

    I do realise that I can mock every other call. But let's say I do not care what else my test wants to load as it may call few other things. How I can make sure that every other requests just "happen silently", maybe offering a single dummy response for everything else?

  • Thomas
    Thomas almost 8 years
    Don't do this in unit tests. There are other ways to load the templates, for example karma-html2js-preprocessor
  • le0diaz
    le0diaz almost 8 years
    Hello @Thomas, I would like to read the real argument behind your "Don't do this in unit tests" affirmation. The main point of my answers is that we are doing endToEnd test and mocking the http responses (The important API services), we don't care about templates coming and usually for test debugging is better to have them as clean as they can be. I agree using html2js for production is a must.
  • Thomas
    Thomas almost 8 years
    using passThrough you need a running server from which you can load the templates. You don't want that dependency in your unit-tests.
  • dmansfield
    dmansfield over 7 years
    @Thomas is right. I never got passThrough to work, and karma-html2js-preprocessor is easy enough to not bother struggling with all the other bs.