AngularJS - это самоуверенная структура, и ее мнение по HTTP-запросам в модульных тестах заключается в том, что все они должны быть издевались.
Не рекомендуется выполнять настоящие HTTP-запросы в модульных тестах по двум причинам. Модульные тесты должны быть изолированы и быть быстрыми. Выполнение реального запроса делает тест асинхронным, что значительно замедляет выполнение тестов. Выполнение реального запроса нарушает изоляцию, факт прохождения теста зависит как от тестируемой единицы, так и от бэкэнд.
Это было учтено, когда был разработан модуль AngularJS ngMock
(он автоматически загружается в модульные тесты с помощью углового mocks.js). Разработчик вряд ли когда-либо сделает asynchronous Жасмин модульные тесты с угловым, потому что нет необходимости делать это.
Тесты интеграции отличаются. Они могут быть не такими широкими, как тесты E2E (которые часто выполняются Protractor) и проверять, как несколько модулей работают вместе, это может включать бэкэнд (HTTP-сервер). Таким образом, в конце Карма и Жасмин все еще используются, но тесты могут быть медленнее и асинхронны и выполнять реальные HTTP-запросы.
Здесь находится модуль ngMockE2E
(обычно используется в тестах E2E). Он включен в угловое mocks.js вместе с ngMock
, но по умолчанию не загружен.
The ngMockE2E is an AngularJS module which contains mocks suitable for end-to-end testing. Currently there is only one mock present in this module - the e2e $httpBackend mock.
ngMockE2E
содержит различные $httpBackend
реализации, которые могут быть использованы для этой цели. Его API меняется. Не предполагается использовать методы flush
и extend
. $rootScope.$digest()
может использоваться, если есть цепочки обещаний $q
, которые должны быть выполнены.
ngMockE2E
не будет работать из коробки должным образом из-за корректировки, которые делаются для угловых услуг ngMock
когда его вспомогательные функции module
и inject
используются. Вспомогательный модуль для ИНТЕГРАЦИИ тестов можно использовать вместо:
angular.module('ngMockI9n', []).config(function ($provide) {
// hack to restore original implementations which were overridden by ngMock
angular.injector(['ng', function ($httpBackendProvider, $browserProvider) {
$provide.provider('$httpBackend', $httpBackendProvider);
$provide.provider('$browserI9n', $browserProvider);
}]);
// make ngMockE2E $httpBackend use original $browser
var httpBackendI9nDecorator = angular.mock.e2e.$httpBackendDecorator
.map(function (dep) {
return (dep === '$browser') ? '$browserI9n' : dep;
});
$provide.decorator('$httpBackend', httpBackendI9nDecorator);
});
Кроме того, рецепт whitelisted real HTTP requests может быть использован для тестирования проще, хотя лучше практика перечислить реальные и издевались запросы в явном виде.
beforeEach(module('app'));
beforeEach(module('ngMockI9n'));
beforeEach(inject(function ($httpBackend) {
$httpBackend.when('GET', '/mocked-request').respond(200, {});
// all other requests will be automatically whitelisted and treated as real
// so make sure that mocked requests are mocked above this point
angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD', 'PUT', 'POST', 'PATCH'],
function (method) {
$httpBackend.when(method).passThrough();
});
}));
it('does real async request', function (done) {
// async tests need extra `done` param
inject(function() {
$http.get('real-request').then(function (response) {
expect(response.data).toEqual(...);
})
.then(done, done.fail);
$rootScope.$digest();
});
});
it('does mocked sync request', function (done) {
// tests with mocked requests are async, too
inject(function() {
$http.get('mocked-request').then(function (response) {
expect(response.data).toEqual(...);
})
.then(done, done.fail);
$rootScope.$digest();
});
});
TL; DR: Использование $httpBackend
из ngMockE2E
в интеграционных тестов для реальных запросов, это требует некоторой дополнительной работы, чтобы сделать его совместимым с ngMock
. Никогда не делайте настоящих запросов в модульных тестах, это приводит к медленным и мутным испытаниям.
Пожалуйста, объясните, что такое «настоящий» HTTP-запрос в вашем случае? – lin
Настоящий запрос - это запрос, который вызывает window.XMLHttpRequest и выполняет запрос на HTTP-сервер. Это не допускается конструкцией в Угловых модульных тестах. – estus
@lin Это автоответчик, кстати. Я считаю эту печально известную проблему. – estus