angularjsangularjs-httpangular-mock

How to mock an angular $http call and return a promise object that behaves like $http


Is there a way to return an HttpPromise (or something similar) to mimic a call to $http? I want to set a global variable that indicates whether the real HTTP request is made or whether a fake HttpPromise object is returned with fake data.

For example, I have a service that is similar to this:

angular
  .module('myservice')
  .factory('MyService', ['$http', function($http) {
      return {
       get : function(itemId) {
         if (isInTestingMode) {
           // return a promise obj that returns success and fake data
         }
         return $http.get("/myapp/items/" + itemId);
       }
    };
 } ]);

And in my controller, I have a call to the aforementioned service that looks similar to this:

        // Somewhere in my controller

        MyService.get($scope.itemId)
           .success(function(data) {
              $scope.item = data;
           })
           .error(function(data, status, headers, config) {
              $scope.notFound = true;
           });

I'm trying to not change the controller code; I want the success and error chaining to still work when in my "isInTestMode". Is it possible to fake an HttpPromise in the way that I described in the service?


Below is a revised edition of the "MyService" above (a snippet) containing a success and error on the promise object. But, how do I execute the success method?

        return {
           get : function(itemId) {
             if (isInTestingMode) {
                var promise = $.defer().promise;
                // Mimicking $http.get's success 
                promise.success = function(fn) {
                  promise.then(function() {
                     fn({ itemId : "123", name : "ItemName"}, 200, {}, {});
                  });
                  return promise;
                };
                // Mimicking $http.get's error 
                promise.error = function(fn) {
                   promise.then(null, function(response) {
                     fn("Error", 404, {}, {});
                   });
                   return promise;
                };
                return promise;
             }
             return $http.get("/myapp/items/" + itemId);
           }
        }

Solution

  • I found that this post is similar to what I was asking.

    However, I wanted a way to mock my service call so that fake data could be returned instead of issuing a true HTTP request call. The best way to handle this situation, for me, is to use angular's $httpBackend service. For example, to bypass a GET request to my "items" resource BUT to not bypass GETs of my partials/templates I would do something like this:

    angular
       .module('myApp', ['ngMockE2E'])
       .run(['$httpBackend', function($httpBackend) {
          $httpBackend
            .whenGET(/^partials\/.+/)
            .passThrough();
          $httpBackend
            .whenGET(/^\/myapp\/items\/.+/)
            .respond({itemId : "123", name : "ItemName"});
    }]);
    

    See this documentation for more information on $httpBackend.