FutuToad
FutuToad

Reputation: 2850

$http mocking is not persistant across tests

Is this set up for $http mocking?

For some reason I am getting this error:

Uncaught Error: Unexpected request: GET http://

describe('DataService tests', function () {

    var errorUrl = "/ErrorReturningURL";
    var successUrl = "/SuccessReturningURL";

    beforeEach(angular.mock.module('app'));

    beforeEach(angular.mock.inject(function ($httpBackend) {
        $httpBackend.when('GET', successUrl).respond('all good!');
        $httpBackend.when('GET', errorUrl).respond(404, '');
    }));

    it('should call the callbackError when http returns error', inject(function (DataService, $httpBackend) {
        var successCallback = jasmine.createSpy();
        var errorCallback = jasmine.createSpy();

        $httpBackend.expectGET(errorUrl);

        DataService.getData(errorUrl, successCallback, errorCallback);

        $httpBackend.flush();

        expect(errorCallback).toHaveBeenCalled();
    }));


}

) ;

service(simplified):

app.service('DataService', function ($http, $parse) {

  this.getData = function (url, callbackSuccess, callbackError) {

      $http.get(url).success( function (data) {

        callbackSuccess( processedData );
      }).error( function (error) {
        callbackError(error);
      });

  };

});

Upvotes: 0

Views: 318

Answers (1)

Ilan Frumer
Ilan Frumer

Reputation: 32357

original $http ?

  • I assume you included angular-mocks.js in your karma.js.conf file.
  • angular-mocks overrides the original $httpBackend , so it is impossible to do real requests.
  • $httpBackend mock has a synchronous API but it must integrate with your asynchronous application.
  • The flush() method is the connecting link between asynchronous applications and synchronous tests.

From $httpBackend docs:

Flushing HTTP requests

The $httpBackend used in production, always responds to requests with responses asynchronously. If we preserved this behavior in unit testing, we'd have to create async unit tests, which are hard to write, follow and maintain. At the same time the testing mock, can't respond synchronously because that would change the execution of the code under test. For this reason the mock $httpBackend has a flush() method, which allows the test to explicitly flush pending requests and thus preserving the async api of the backend, while allowing the test to execute synchronously

You must call flush() to actually make the request:

 $httpBackend.expectGET(errorUrl);

 DataService.getData(errorUrl, successCallback, errorCallback);
  
 $httpBackend.flush();

 expect(errorCallback).toHaveBeenCalled();

Upvotes: 2

Related Questions