Pertanyaan Cara mengejek panggilan http $ sudut dan mengembalikan objek janji yang berperilaku seperti $ http


Apakah ada cara untuk mengembalikan HttpPromise (atau sejenisnya) untuk meniru panggilan ke $http? Saya ingin menetapkan variabel global yang menunjukkan apakah permintaan HTTP yang sebenarnya dibuat atau apakah objek HttpPromise palsu dikembalikan dengan data palsu.

Sebagai contoh, saya memiliki layanan yang mirip dengan ini:

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

Dan di pengontrol saya, saya memiliki panggilan ke layanan tersebut yang terlihat mirip dengan ini:

        // Somewhere in my controller

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

saya mencoba untuk tidak mengubah kode pengontrol; Saya mau itu success dan error chaining untuk tetap bekerja ketika di "isInTestMode" saya. Apakah mungkin untuk memalsukan suatu HttpPromise dengan cara yang saya jelaskan di layanan?


Di bawah ini adalah edisi yang direvisi dari "MyService" di atas (cuplikan) yang berisi a success dan error pada objek janji. Tapi, bagaimana cara mengeksekusi success metode?

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

16
2018-06-24 15:11


asal


Jawaban:


Cukup gunakan deferred metode dari $qlayanan

    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
    }

Dan kemudian Anda dapat memanggil fungsi Anda seperti $http janji (Anda harus menyesuaikan apa pun yang Anda ingin masukkan ke dalamnya, tentu saja).

    fakeHttpCall(true).then(
      function (data) {
        // success callback
        console.log(data)
      },
      function (err) {
        // error callback
        console.log(err)
      })

15
2018-06-24 15:26



Saya menemukan itu posting ini mirip dengan apa yang saya tanyakan.

Namun, saya ingin cara untuk mengejek panggilan layanan saya sehingga data palsu dapat dikembalikan daripada mengeluarkan panggilan permintaan HTTP yang benar. Cara terbaik untuk menangani situasi ini, bagi saya, adalah menggunakan sudutnya $httpBackend layanan. Misalnya, untuk melewati permintaan GET ke sumber daya "item" saya, TAPI untuk tidak bypass GETs dari parsial / template saya, saya akan melakukan sesuatu seperti ini:

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

Lihat dokumentasi ini untuk informasi lebih lanjut tentang $ httpBackend.


6
2018-06-24 21:46



Saya akhirnya menemukan cara menggunakan jasmin. $httpBackend tidak ada pilihan untuk saya, karena ada juga metode-metode $ http yang saya butuhkan untuk mengejek layanan yang sama. Saya juga berpikir bahwa tes pengontrol perlu menentukan url tidak sempurna seperti imho controller dan tesnya seharusnya tidak perlu mengetahuinya.

Berikut ini cara kerjanya:

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

4
2018-05-04 10:07



Anda dapat mengimplementasikan kelas FakeHttp Anda:

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

Kemudian dalam kode Anda, Anda akan mengembalikan falseHttp palsu baru dari janji.

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

Janji itu harus tidak sinkron, jika tidak, itu tidak akan berhasil. Untuk itu Anda bisa menggunakan $ timeout.


0
2018-02-16 10:25



mudah sekali!

Anda dapat melakukannya menggunakan angular-mengolok-as-async seperti ini:

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;

    });

}]);

0
2017-09-14 20:58