Mocking $httpBackend - how to handle "Unexpected request, No more request expected"?
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
Comments
-
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 almost 8 yearsDon't do this in unit tests. There are other ways to load the templates, for example karma-html2js-preprocessor
-
le0diaz almost 8 yearsHello @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 almost 8 yearsusing passThrough you need a running server from which you can load the templates. You don't want that dependency in your unit-tests.
-
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.