Активировать $httpMock после инициализации углового приложения

Я хочу иметь возможность включать и выключать макет $httpBackend в моем приложении angularJS.

Это означает, что я хочу внедрить $httpBackend лениво/по требованию. Также было бы неплохо иметь возможность включать и выключать его снова.

Например, чтобы предоставить входные данные для приложения AngularJS, которое предварительно просматривается из CMS.

Приведенный ниже код работает, только если я перемещаю ngMockE2E в обычную зависимость и ввожу $httpBackend в свою фабрику стандартным способом.

Код устанавливает upp $httpBackend для всех вызовов из файла конфигурации, а затем отвечает на все из них...

const registerCalls = () => {
    const injectormock = angular.injector(['ngMockE2E']); //lazy load not working as expected
    const $httpBackend = injectormock.get('$httpBackend'); //lazy load not working as expected.
    //Pass through for resources:
    $httpBackend.whenGET(/.*.html/).passThrough();
    $httpBackend.whenGET(/.*.json/).passThrough();
    //API calls should be mocked:
    const apiCalls = {};
    for (var call in apiConfig) {
        if ({}.hasOwnProperty.call(apiConfig, call)) {
            const callConfig = apiConfig[call];
            const url = angular.isDefined(callConfig.regex) ? callConfig.regex : callConfig.url();
            if (callConfig.method === 'GET') {
                apiCalls[call] = $httpBackend.whenGET(url);
            } else if (callConfig.method === 'POST') {
                apiCalls[call] = $httpBackend.whenPOST(url);
            }
        }
    }
    return apiCalls;

}

const success = function() {
    const apiCalls = registerCalls();
    for (var call in apiConfig) {
        let response = {};
        if (angular.isDefined(apiConfig[call].response)) {
            response = apiConfig[call].response();
        }
        apiCalls[call].respond(200, response);
    }
};

Как настроить $httpBackend, чтобы его можно было активировать/деактивировать во время работы приложения AngularJS?


person David Karlsson    schedule 10.04.2017    source источник


Ответы (1)


Сервисы Angular — это синглтоны, которые лениво создаются при первой инъекции. Если инъекция $httpBackend выполняется при начальной загрузке приложения (что обычно бывает при использовании $http), невозможно имитировать службу.

Получение версии E2E $httpBackend через angular.injector — очевидный, но неправильный способ сделать это. Это приведет к созданию нового экземпляра инжектора, который использует свои собственные синглтоны основной службы ($browser и т. д.).

Чистый способ сделать это через angular.mock.e2e global, как показано в этом примере. Он будет доступен после углового -mocks.js загружается. Суть в том, чтобы украсить $httpBackend (функция), чтобы обернуть как оригинальную, так и E2E-реализации и использовать их условно.

Это можно сделать так:

angular.module('mockableHttp', [])
.decorator('$httpBackend', function ($injector, $delegate) {
  var $httpBackendOriginal = $delegate;
  var $httpBackendE2E = $injector.invoke(angular.mock.e2e.$httpBackendDecorator, null, {
    $delegate: $delegate
  });

  function $httpBackend() {
    var $httpBackendImplementation = $httpBackend.isMocking
      ? $httpBackendE2E
      : $httpBackendOriginal;

    return $httpBackendImplementation.apply(this, arguments);
  }

  return Object.assign($httpBackend, $httpBackendE2E, {
    enableMocking: function() {
      $httpBackend.isMocking = true;
    },
    disableMocking: function() {
      $httpBackend.isMocking = false;
    }
  });
});

Где mockableHttp загружается в модуль приложения (может быть полностью исключен в производстве), а макеты HTTP активируются с помощью $httpBackend.enableMocking().

person Estus Flask    schedule 10.04.2017