如何模拟一个有角度的$ http调用并返回一个行为类似$ http的promise对象

why*_*ite 19 angularjs angularjs-http angular-mock

有没有办法返回一个模仿调用的HttpPromise(或类似的东西)$http?我想设置一个全局变量,指示是否发出了真正的HTTP请求,或者是否使用伪数据返回了假的HttpPromise对象.

例如,我有一个与此类似的服务:

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);
       }
    };
 } ]);
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我调用上述类似于此的服务:

        // Somewhere in my controller

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

我试图改变控制器代码; 在我的"isInTestMode"中,我希望successerror链接仍然有效.是否有可能以HttpPromise我在服务中描述的方式伪造一个?


下面是上面的"MyService"修订版(一个片段),其中包含一个successerror在promise对象上.但是,我该如何执行该success方法?

        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);
           }
        }
Run Code Online (Sandbox Code Playgroud)

dom*_*kun 17

只需使用服务的deferred方法$q

    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 you fake $http call")
      }

      return deferred.promise
    }
Run Code Online (Sandbox Code Playgroud)

然后你可以像$http承诺一样调用你的函数(当然,你必须自定义你想要放在其中的任何东西).

    fakeHttpCall(true).then(
      function (data) {
        // success callback
        console.log(data)
      },
      function (err) {
        // error callback
        console.log(err)
      })
Run Code Online (Sandbox Code Playgroud)

  • 我很确定这不会起作用,因为`deferred.promise`没有提供`success()`和`error()`用于链接,比如$ http.有关如何实现这一点,请参阅此答案 - http://stackoverflow.com/a/19747182/404099. (4认同)
  • @IliaBarahovski`seccess()`和`error()`不再使用了.Promises为您提供了`then(成功,错误)`构造,它更强大,可以链接到无限.请参阅https://docs.angularjs.org/api/ng/service/$q (2认同)

why*_*ite 6

我发现这篇文章与我的要求类似.

但是,我想要一种模拟我的服务调用的方法,以便可以返回伪数据而不是发出真正的HTTP请求调用.对我来说,处理这种情况的最好方法是使用angular的$httpBackend服务.例如,绕过GET请求到我的"items"资源但是绕过我的partials/templates的GET我会做这样的事情:

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

有关$ httpBackend的更多信息,请参阅此文档.