4

I'm new to AngularJS and running into some problems with unit testing. I've seen countless examples of mocking $httpBackend calls, but when I do that it won't work unless I also include $rootScope.$apply().

My service:

angular.module('myApp.services', ['ngResource'])
  .factory('TestingService', ['$resource', function($resource) {
    return $resource('/api/v1/values', {}, {
      getValues: {
        method: 'GET'
      }
    });
  }]);

My unit test:

describe('Testing services', function() {
  beforeEach(module('myApp.services'));

  afterEach(function() {
    inject(function($httpBackend) {
      $httpBackend.verifyNoOutstandingExpectation();
      $httpBackend.verifyNoOutstandingRequest();
    });
  });

  describe('TestingService', function() {
    it('would be nice to get an explanation for this',
        inject(['$rootScope', '$httpBackend', 'TestingService', 
          function ($rootScope, $httpBackend, testingService) {

          $httpBackend.expectGET('/api/v1/values').respond(100);

          var result = testingService.getValues();
          //$rootScope.$apply();

          $httpBackend.flush();
          expect(result).toBe(100);
          alert(result);
      }])
    );
  });
});

When Karma runs the test like this I get:

Error: No pending request to flush !
Error: Unsatisfied requests: GET /api/v1/values

And if I include the $rootScope.$apply(); I'll get this (and the alert of course also prints out a $promise):

Expected { $promise : { then : Function, catch : Function, finally : Function }, $resolved : true } to be 100.

Can anyone explain why I need "$rootScope.$apply();" to pass the expectGET? And why the response is a promise instead of the mock response I've specified?

1
  • 1
    The response is not a promise, its the Resource object which contains a promise. And you don't need $rootScope.$apply() at all. The actual test has to be either of the two ways I created here in plunkr. What is disturbing me is that I can replicate your problem where it should pass tests instead. Commented Mar 23, 2014 at 4:21

1 Answer 1

2

Found the problem after some sleep. Simple one fortunately.

I'm using Angular version 1.3.0-beta.2, but had an older version for angular-mocks. Updating the versions removes the need for "$root.$apply();".

The updated working test:

describe('Testing services', function() {
  beforeEach(function(){
    module('myApp.services');
    this.addMatchers({
      toEqualData: function(expected) {
        return angular.equals(this.actual, expected);
      }
    });
  });

  afterEach(function() {
    inject(function($httpBackend) {
      $httpBackend.verifyNoOutstandingExpectation();
      $httpBackend.verifyNoOutstandingRequest();
    });
  });

  describe('TestingService', function() {
    it('should work',
        inject(['$rootScope', '$httpBackend', 'TestingService', 
          function ($rootScope, $httpBackend, testingService) {

          $httpBackend.expectGET('/api/v1/values').respond( { key: 'value' } );

          var result = testingService.getValues();

          $httpBackend.flush();
          expect(result).toEqualData( { key: 'value' } );
          alert(angular.toJson(result, true));
      }])
    );
  });
});
Sign up to request clarification or add additional context in comments.

1 Comment

My plunkr had all the versions correct but still I am unable to assert the response status. Have you tried asserting the status?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.