Hay una manera de devolver un HttpPromise (o algo similar) para simular una llamada a $http? Quiero establecer una variable global que indica si la verdadera solicitud HTTP o si un falso HttpPromise objeto es devuelto con datos falsos.

Por ejemplo, que tiene un servicio que es similar a este:

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);
       }
    };
 } ]);

Y en mi controlador, tengo una llamada para el mencionado servicio que se parece a esto:

        //Somewhere in my controller

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

Estoy tratando de no cambiar el código de controlador; quiero que el success y error encadenamiento a trabajar aún cuando en mi “isInTestMode”.
Es posible simular el HttpPromise en la forma que he descrito en el servicio?


A continuación es una edición revisada de la “MyService” (un fragmento), que contiene un success y error en la promesa de objeto. Pero, ¿cómo puedo ejecutar el success método?

        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);
           }
        }

OriginalEl autor whyceewhite | 2014-06-24

5 Comentarios

  1. 16

    Solo uso el deferred método de la $qservicio

        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
        }

    Y, a continuación, usted puede llamar a su función como un $http promesa (usted tiene que personalizar lo que quieras poner dentro de ella, por supuesto).

        fakeHttpCall(true).then(
          function (data) {
            //success callback
            console.log(data)
          },
          function (err) {
            //error callback
            console.log(err)
          })
    Yo no estoy en la comprensión de cómo el éxito o el error está obligado a ejecutar. He actualizado mi pregunta con una amplia ejemplo basado en sus comentarios. No veo cómo podría forzar el éxito del método dentro de la “conseguir” en el MyService.
    usted sólo debe fijar el deferred.resolve(result) y, a continuación, devolver la promesa si desea simular el éxito…. o conjunto de deferred.reject(error) si desea simular un fracaso
    Estoy bastante seguro de que esto no va a funcionar como deferred.promise no proporciona success() y error() para el encadenamiento, como $http. Ver esta respuesta, por ejemplo, de cómo lograr que – stackoverflow.com/a/19747182/404099.
    success() y error() no se utilizan más. Promesas que le da la then( success, error ) construir, que es más potente y puede ser encadenado a infinito. Consulte docs.angularjs.org/api/ng/service/$p
    usted está totalmente a la derecha, yo estaba predicando derecho pero escribir mal 🙂

    OriginalEl autor domokun

  2. 6

    He encontrado que este post es similar a lo que me estaba pidiendo.

    Sin embargo, yo quería una forma de burlarse de mi llamada de servicio, de modo que los datos falsos, podrían ser devueltos en lugar de emitir una verdadera HTTP de petición de llamada. La mejor manera de manejar esta situación, para mí, es el uso de angulares del $httpBackend servicio. Por ejemplo, para la derivación de una petición GET a mi “elementos” de los recursos, PERO a no bypass se Pone de mi parciales/plantillas me gustaría hacer algo como esto:

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

    Ver esta documentación para obtener más información sobre los $httpBackend.

    OriginalEl autor whyceewhite

  3. 4

    Finalmente me encontró una manera de utilizar jasmin. $httpBackend era ninguna opción para mí, como lo eran también los no$http-métodos necesitaba simulacro en el mismo servicio. Yo también creo que la prueba de la controladora necesidad de especificar la dirección url no es perfecta en mi humilde opinión el controlador y su prueba no debe necesita saber acerca de él.

    Aquí es cómo funciona:

    beforeEach(inject(function ($controller, $rootScope, $q) {
      scope = $rootScope.$new();
      mockSvc = {
        someFn: function () {
        },
        someHttpFn: function () {
        }
      };
    
      //use jasmin to fake $http promise response
      spyOn(mockSvc, 'someHttpFn').and.callFake(function () {
        return {
          success: function (callback) {
            callback({
             //some fake response
            });
          },
          then: function(callback) {
             callback({
             //some fake response, you probably would want that to be
             //the same as for success 
             });
          },
          error: function(callback){
            callback({
             //some fake response
            });             
          }
        }
      });
    
      MyCtrl = $controller('MyCtrl', {
        $scope: scope,
        MyActualSvc: mockSvc
      });
    }));

    OriginalEl autor hugo der hungrige

  4. 0

    Puede implementar su FakeHttp clase:

    var FakeHttp = function (promise) {
        this.promise = promise;
        this.onSuccess = function(){};
        this.onError = function(){};
        this.premise.then(this.onSuccess, this.onError);
    };
    FakeHttp.prototype.success = function (callback) {
        this.onSuccess = callback;
        /**You need this to avoid calling previous tasks**/
        this.promise.$$state.pending = null;
        this.promise.then(this.onSucess, this.onError);
        return this;
    };
    FakeHttp.prototype.error = function (callback) {
        this.onError = callback;
        /**You need this to avoid calling previous tasks**/
        this.promise.$$state.pending = null;
        this.promise.then(this.onSuccess, this.onError);
        return this;
    };

    A continuación, en el código, se volvería un nuevo fakeHttp de la promesa.

    if(testingMode){
        return new FakeHttp(promise);
    };

    La promesa debe ser asíncrona, de lo contrario no funcionará. Para que se puede usar $timeout.

    OriginalEl autor Gabriel Furstenheim

  5. 0

    easy peasy!

    Puede hacerlo usando angular-se burla-async así:

    var app = ng.module( 'mockApp', [
        'ngMockE2E',
        'ngMockE2EAsync'
    ]);
    
    app.run( [ '$httpBackend', '$q', function( $httpBackend, $q ) {
    
        $httpBackend.whenAsync(
            'GET',
            new RegExp( 'http://api.example.com/user/.+$' )
        ).respond( function( method, url, data, config ) {
    
            var re = /.*\/user\/(\w+)/;
            var userId = parseInt(url.replace(re, '$1'), 10);
    
            var response = $q.defer();
    
            setTimeout( function() {
    
                var data = {
                    userId: userId
                };
                response.resolve( [ 200, "mock response", data ] );
    
            }, 1000 );
    
            return response.promise;
    
        });
    
    }]);

    OriginalEl autor Assaf Moldavsky

Dejar respuesta

Please enter your comment!
Please enter your name here