在角1.x单元/集成测试中,发出未被$httpBackend.when模拟的请求会导致错误:
错误:意外请求:获取/实请求
是否有可能使用ngMock和Karma+Jasmine测试平台发出真正的HTTP请求?做这件事的好方法是什么?
发布于 2017-02-19 19:11:37
AngularJS是一个自以为是的框架,它在单元测试中对HTTP请求的看法是,所有这些请求都应该被模拟。
出于两个原因,在单元测试中执行真正的HTTP请求是不可取的。单元测试应该是隔离的和快速的。发出真正的请求会导致测试异步,这会显著降低测试的运行速度。真正的请求打破了隔离,如果测试通过取决于测试单元和后端。
在设计AngularJS ngMock模块时考虑到了这一点(它是由角-mocks.js在单元测试中自动加载的)。开发人员几乎不会用角度进行异步 Jasmine单元测试,因为没有必要这样做。
集成测试各不相同。它们可能不如E2E测试(通常由Protractor运行)和测试几个单元是如何协同工作的,这可能包括一个后端(HTTP )。因此,最终仍然使用Karma和Jasmine,但是测试可能比较慢,而且是异步的,并且可以执行真正的HTTP请求。
这就是ngMockE2E模块(通常用于E2E测试)的开始位置。它与ngMock一起包含在角mocks.js中,但默认情况下不加载。
ngMockE2E是一个AngularJS模块,包含适合端到端测试的模拟.目前,这个模块中只有一个模拟-- e2e $httpBackend模拟。
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);
});此外,可以使用白名单的真实HTTP请求的配方来简化测试,尽管最佳实践是显式地枚举真实的和模拟的请求。
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();
});
});在实际请求的集成测试中使用来自$httpBackend ngMockE2E 的,这需要一些额外的工作才能使其与 ngMock**.兼容。永远不要在单元测试中执行真正的请求,这会导致缓慢和无用的测试。
https://stackoverflow.com/questions/42331583
复制相似问题