Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS+Jasmine: $httpBackend not working as expected

Tags:

I'm using Jasmine with Karma to test my app built on Angular.

I've to test a service that loads user data and I'm using $httpBackend to mock the responses. However, when I run the test, I got two errors:

  • Error: No pending request to flush!
  • Error: Unsatisfied requests: GET https://api.github.com/users/wilk

Module:

'use strict';  app.service ('UserService', ['$resource', '$q', 'GITHUB_API_URL', function ($resource, $q, GITHUB_API_URL) {   var userResource = $resource (GITHUB_API_URL + '/users/:user', {user: '@user'}) ,       userModel = {};    return {     data: function () {         return userModel;     } ,     populate: function (user) {       var deferred = $q.defer () ,           userRequest = userResource.get ({user: user});        $q           .when (userRequest.$promise)           .then (function (data) {               userModel = data;               deferred.resolve (data);           });        return deferred.promise;     }   }; }]); 

Test:

'use strict';  describe ('Service: UserService', function () {     beforeEach (module ('myApp'));      var $appInjector = angular.injector (['myApp']) ,         UserService = $appInjector.get ('UserService') ,         GITHUB_API_URL = $appInjector.get ('GITHUB_API_URL') ,         GITHUB_USER = $appInjector.get ('GITHUB_USER') ,         $httpBackend;      beforeEach (inject (function ($injector) {         $httpBackend = $injector.get ('$httpBackend');          $httpBackend             .when ('GET', GITHUB_API_URL + '/users/' + GITHUB_USER)             .respond ({                 login: GITHUB_USER ,                 id: 618009             });     }));      afterEach (function () {         $httpBackend.verifyNoOutstandingExpectation ();         $httpBackend.verifyNoOutstandingRequest ();     });      describe ('when populate method is called', function () {         it ('should returns user data', function () {             $httpBackend.expectGET (GITHUB_API_URL + '/users/' + GITHUB_USER);              UserService.populate (GITHUB_USER);             $httpBackend.flush ();             expect(UserService.data ()).toEqual ({                 login: GITHUB_USER ,                 id: 618009             });          });     }); }); 

Let's assume that GITHUB_API_URL is equal to 'https://api.github.com/' and GITHUB_USER is equal to 'wilk'.

I'm running this test with Karma-Jasmine 0.1.5 and AngularJS 1.2.6 (with Angular Mocks and Scenario 1.2.6).

What's wrong with this code?

like image 890
Wilk Avatar asked Feb 05 '14 12:02

Wilk


1 Answers

Let's talk about each error separately:

Error: No pending request to flush!

That's happening because no request was made through $httpBackend, so there's nothing to flush. That's because you are instantiating UserService before $httpBackend and so Angular doesn't know it should use it instead of the real $http. If you check out the console you'll see that a real request is being sent.

Error: Unsatisfied requests: GET https://api.github.com/users/wilk

Same reason as the above. Since $httpBackend isn't being used by the service, the expectation you've created is never fulfilled.

Here's your spec refactored after considering all of the above:

describe ('Service: UserService', function () {     var UserService,         GITHUB_API_URL,         GITHUB_USER,         $httpBackend;      beforeEach(function() {       module('plunker');        inject(function( _$httpBackend_, _UserService_, _GITHUB_API_URL_, _GITHUB_USER_) {         $httpBackend = _$httpBackend_;         UserService = _UserService_;         GITHUB_API_URL = _GITHUB_API_URL_;         GITHUB_USER = _GITHUB_USER_;       });     });      afterEach (function () {         $httpBackend.verifyNoOutstandingExpectation ();         $httpBackend.verifyNoOutstandingRequest ();     });      describe ('when populate method is called', function () {         it ('should returns user data', function () {             $httpBackend               .whenGET(GITHUB_API_URL + '/users/' + GITHUB_USER)               .respond ({                   login: GITHUB_USER,                   id: 618009               });               UserService.populate(GITHUB_USER);             $httpBackend.flush();              expect(UserService.data().login).toBe(GITHUB_USER);             expect(UserService.data().id).toBe(618009);         });     }); }); 

Plunker

Note: I've changed the way things were being injected a little bit, but the way you are doing is just fine, as long as you create $httpBackend before everything else.

like image 105
Michael Benford Avatar answered Oct 11 '22 05:10

Michael Benford