Est*_*ask 4 javascript integration-testing unit-testing jasmine angularjs
$httpBackend.when在Angular 1.x单元/集成测试中发出未被模拟的请求会导致错误:
错误:意外请求:GET/real-request
是否可以使用ngMock和Karma + Jasmine测试装备进行真正的HTTP请求?这样做的好习惯是什么?
AngularJS是一个自以为是的框架,它对单元测试中的HTTP请求的意见是所有这些都应该被嘲笑.
由于两个原因,不建议在单元测试中执行真正的HTTP请求.单元测试应该是隔离的并且速度很快.发出实际请求会使测试异步,这会显着降低测试运行速度.提出真正的请求会打破隔离,如果测试通过,则取决于测试单元和后端.
ngMock设计AngularJS 模块时会考虑这一点(它由angular-mocks.js在单元测试中自动加载).开发人员几乎不会使用Angular 进行异步 Jasmine单元测试,因为没有必要这样做.
集成测试不同.它们可能不像E2E测试那样广泛(通常由Protractor运行)并测试多个单元如何协同工作,这可能包括后端(HTTP服务器).所以最终仍然使用了Karma和Jasmine,但是测试可能会更慢并且异步并且可以执行真正的HTTP请求.
这是ngMockE2E模块(通常在E2E测试中使用)开始的地方.它包含在angular-mocks.js旁边ngMock但默认情况下不加载.
ngMockE2E是一个AngularJS模块,其中包含适用于端到端测试的模拟.目前这个模块中只有一个模拟 - e2e $ httpBackend模拟.
ngMockE2E包含$httpBackend可用于此目的的不同实现.它的API各不相同.它不应该使用flush和extend方法.$rootScope.$digest()如果存在$q应该执行的promise链,则可以使用.
ngMockE2E由于Angular服务的ngMock辅助功能module和inject使用时对Angular服务进行了调整,因此无法正常使用.可以使用用于集成测试的辅助模块:
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);
});
Run Code Online (Sandbox Code Playgroud)
此外,可以使用白名单真实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();
});
});
Run Code Online (Sandbox Code Playgroud)
TL; DR:使用$httpBackend来自ngMockE2E于集成测试真正的要求,这需要一些额外的工作,使其与兼容ngMock.在单元测试中永远不要做真正的请求,这会导致测试缓慢且无用.
| 归档时间: |
|
| 查看次数: |
1021 次 |
| 最近记录: |