Следите за зависимостями службы - PullRequest
0 голосов
/ 26 февраля 2019

Мне интересно, как лучше шпионить за зависимостями, чтобы я мог убедиться, что их методы вызываются в моих службах.Я сократил свой код, чтобы сосредоточиться на проблеме под рукой.Я могу нормально проверить свой сервис, но я также хочу подтвердить, что мой сервис (в данном случае metricService) имеет методы, которые также вызываются.Я знаю, что должен каким-то образом использовать createSpyObj, но пока функция выполняется правильно, методы spyObj не перехватываются.Должен ли я даже использовать createSpyObj?Или я должен использовать spyObj?Я не совсем понимаю концепцию шпионажа, когда речь идет о зависимостях.

ОБНОВЛЕНИЕ: при использовании SpyOn я вижу, что вызывается один метод, но другие методы не

Test.spec

describe("Catalogs service", function() {

  beforeEach(angular.mock.module("photonServicesCommons"));

  var utilityService, metricsService, loggerService, catalogService, localStorageService;

  var $httpBackend, $q, $scope;

  beforeEach(
    inject(function(
      _catalogService_,
      _metricsService_,
      _$rootScope_,
      _$httpBackend_
    ) {
      catalogService = _catalogService_;
      $scope = _$rootScope_.$new();
      $httpBackend = _$httpBackend_;
      $httpBackend.when('GET', "/ctrl/catalog/all-apps").respond(
        {
          catalogs: catalogs2
        }
      );

      metricsService = _metricsService_;
      startScope = spyOn(metricsService, 'startScope')
      emitSuccess = spyOn(metricsService, 'emitGetCatalogSuccess').and.callThrough();
      endScope = spyOn(metricsService, 'endScope');
    })
  );



  afterEach(function(){
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  describe('get catalog', function(){
    it("Should get catalogs", function(done) {
      catalogService.normalizedDynamicAppList = testDynamicAppList1;
      catalogService.response = null;
      var promise3 = catalogService.getCatalog();
      promise3.then(function (res) {
      expect(res.catalogs).toEqual(catalogs2);
      });
      expect(metricsService.startScope).toHaveBeenCalled();
      expect(metricsService.emitGetCatalogSuccess).toHaveBeenCalled();
      expect(metricsService.endScope).toHaveBeenCalled();

      $scope.$digest();
      done();
      $httpBackend.flush();
    });
  });

});

Сервис

public getCatalog(): IPromise<Interfaces.CatalogsResponse> {
  if (this.response !== null) {
    let finalResponse:any = angular.copy(this.response);
    return this.$q.when(finalResponse);
  }

  return this.$q((resolve, reject) => {
    this.metricsService.startScope(Constants.Photon.METRICS_GET_CATALOG_TIME);
    this.$http.get(this.catalogEndpoint).then( (response) => {
      let data: Interfaces.CatalogsResponse = response.data;
      let catalogs = data.catalogs;
      if (typeof(catalogs)) { // truthy check
        catalogs.forEach((catalog: ICatalog) => {
          catalog.applications.forEach((application: IPhotonApplication) => {
            if( !application.appId ) {
              application.appId = this.utilityService.generateUUID();
            }
          })
        });

      } else {
        this.loggerService.error(this.TAG, "Got an empty catalog.");
      }
      this.response = data;
      this.metricsService.emitGetCatalogSuccess();
      console.log("CALLING END SCOPE");
      this.metricsService.endScope(Constants.Photon.METRICS_GET_CATALOG_TIME);
      resolve(finalResponse);
    }).catch((data) => {
      this.loggerService.error(this.TAG, "Error getting apps: " + data);
      this.response = null;
      this.metricsService.emitGetCatalogFailure();
      reject(data);
    });
  });
} // end of getCatalog()

1 Ответ

0 голосов
/ 26 февраля 2019

Вместо использования createSpyObj вы можете просто использовать spyOn.Как в:

beforeEach(
  inject(function(
    _catalogService_,
    _$rootScope_,
    _$httpBackend_,
    _metricsService_ //get the dependecy from the injector & then spy on it's properties
  ) {
    catalogService = _catalogService_;
    metricsService = _metricsService_; 
    $scope = _$rootScope_.$new();
    ...
    // create the spy object for easy referral later on
    someMethodSpy = jasmine.spyOn(metricsService, "someMethodIWannaSpyOn")
})
);

describe('get catalog', function(){
  it("Should get catalogs", function(done) {
    catalogService.normalizedDynamicAppList = testDynamicAppList1;
    catalogService.response = null;
    var promise3 = catalogService.getCatalog();
    ...other expects
    ...
    //do the spy-related expectations on the function spy object
    $httpBackend.flush(); // this causes the $http.get() to "move forward" 
    // and execution moves into the .then callback of the request. 
    expect(someMethodSpy).toHaveBeenCalled(); 
  });
});

Я использовал этот шаблон при тестировании сложных угловых приложений, а также оборачивал внешние импортированные / глобальные зависимости в угловые сервисные оболочки, чтобы позволить шпионить и издеваться над ними для тестирования.

Причина, по которой createSpyObject не сработает, заключается в том, что при его использовании будет создан совершенно новый объект metricService с указанными шпионскими реквизитами.Это не будет тот же «metricService», который вводится в сервис, проверяемый угловым инжектором.Вы хотите получить тот же сервисный объект-одиночка из инжектора, а затем шпионить за его свойствами.

Другим источником дисфункции было местоположение $httpBackend.flush() s.$httpBackend - это макет для службы $ http: вы заранее определяете любое количество ожидаемых HTTP-запросов, которые будут сделаны кодом, который вы тестируете.Затем, когда вы вызываете функцию, которая внутренне использует $ http для запроса некоторого URL-адреса, вместо этого $ httpBackend перехватывает вызов метода $ http (и может выполнять такие действия, как проверка полезной нагрузки и заголовков запроса и ответ).Обработчики then / error для вызова $http называются только после , тестовый код вызывает $httpBackend.flush().Это позволяет вам выполнять любые настройки, необходимые для подготовки некоторого состояния теста, и только затем запускать обработчик .then и продолжать выполнение асинхронной логики.

Лично для меня то же самое происходит каждый раз, когда я пишу тесты с $ httpBackend, и всегда требуется время, чтобы выяснить или запомнить :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...