Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
           }
        }
like image 414
whyceewhite Avatar asked Jun 24 '14 15:06

whyceewhite


People also ask

How to make HTTP GET API request using ECMAScript promise in angular?

The HttpClientModule is required to trigger HTTP calls from the Angular applications . Now, open the app.component.ts file, then we will add code to make HTTP Get API request and handle the response using the ECMAScript Promise in Angular. In the constructor, inject the HttpClient service.

How to send HTTP request using httpclient in angular?

Next, go to the app.component.ts file. Here we will write the core logic to make the HTTP GET request and manage the response using the ES6 Promise in Angular. You simply import HttpClient and you can now inject HttpClient in a component and use it to send API requests.

How to trigger HTTP calls in angular using promises?

Now, we will trigger HTTP calls in Angular by using Promises and handle the Success and Error callbacks. Open the app.module.ts file then import the HttpClientModule and update the imports array.

How to use promise in angular to fetch posts data?

Declare getPosts () custom function inside this function use Promise to fetch the posts data. We declared the promise instance in the Angular custom method with new keyword and passed the resolve and reject method in it. We set up the apiURL in the getPosts function and made the Http Get request followed by the toPromise () method.


2 Answers

Just use the deferred method of the $qservice

    var fakeHttpCall = function(isSuccessful) {
    
      var deferred = $q.defer()
    
      if (isSuccessful === true) {
        deferred.resolve("Successfully resolved the fake $http call")
      }
      else {
        deferred.reject("Oh no! Something went terribly wrong in your fake $http call")
      }
      
      return deferred.promise
    }

And then you can call your function like an $http promise (you have to customize whatever you want to put inside of it, of course).

    fakeHttpCall(true).then(
      function (data) {
        // success callback
        console.log(data)
      },
      function (err) {
        // error callback
        console.log(err)
      })
like image 71
domokun Avatar answered Oct 07 '22 16:10

domokun


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.

like image 45
whyceewhite Avatar answered Oct 07 '22 16:10

whyceewhite