当前位置: 首页 > 面试题库 >

在AngularJS单元/集成测试中向HTTP服务器发出真实请求

舒飞捷
2023-03-14
问题内容

发出未$httpBackend.when在Angular 1.x单元/集成测试中模拟的请求会导致错误:

错误:意外的请求:GET / real-request

是否可以使用ngMockKarma + Jasmine测试设备发出真正的HTTP请求?有什么好的做法?


问题答案:

AngularJS是有思想的框架,它对单元测试中的HTTP请求的看法是所有这些都应该被模拟。

不建议在单元测试中执行真实的HTTP请求,这有两个原因。单元测试应该是隔离的并且是快速的。发出真实请求会使测试异步,这会大大降低测试运行速度。发出真实请求会破坏隔离,测试通过的事实取决于被测单元和后端。

ngMock设计AngularJS 模块时已考虑到了这一点(它由angular-
mocks.js在单元测试中自动加载)。开发人员几乎不会使用Angular
进行异步 Jasmine单元测试,因为不需要这样做。

集成测试有所不同。它们可能不像E2E测试(通常由量角器运行)那样广泛,并测试多个单元如何协同工作,其中可能包括后端(HTTP服务器)。因此最后仍然使用Karma和Jasmine,但是测试可能会比较慢且异步,并且会执行真正的HTTP请求。

这是ngMockE2E模块(通常用于E2E测试中)插入的位置。它与angular-mocks.js一起包含,ngMock但默认情况下未加载。

ngMockE2E是一个AngularJS模块,其中包含适用于端到端测试的模拟。当前,此模块中仅提供一个模拟-e2e $ httpBackend模拟。

ngMockE2E包含$httpBackend可以用于此目的的不同实现。其API有所不同。它不应该使用flushextend方法。$rootScope.$digest()如果有$q应执行的承诺链,则可以使用。

ngMockE2E由于Angular服务的ngMock助手功能moduleinject使用时对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);
});

此外,用于白名单的真实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();
  });
});

TL;DR:使用$httpBackend来自ngMockE2E于集成测试真正的要求,这需要一些额外的工作,使其与兼容ngMock。永远不要在单元测试中执行真正的请求,这会导致测试缓慢而浪费资源。



 类似资料:
  • 本文向大家介绍AngularJS 单元测试服务,包括了AngularJS 单元测试服务的使用技巧和注意事项,需要的朋友参考一下 示例 服务编号 考试 跑!

  • 测试这种服务的基本策略是验证请求的内容(正确的URL),并确保我们模拟到服务中的数据通过正确的方法正确返回。 wikisearch.ts 我们的测试策略是检查服务是否已请求正确的网址,一旦我们回复了模拟数据,我们就要验证它是否返回相同的数据。

  • 问题内容: 我正在测试服务A,但是服务A取决于服务B(即服务B已注入服务A)。 我已经看到了这个问题,但是我的情况有所不同,因为我认为_模拟_ 服务B而不是注入服务B的实际实例更有意义。我将用茉莉间谍对其进行模拟。 这是一个示例测试: 我得到的错误是: 错误:未知提供程序:serviceBProvider 我该怎么做? 问题答案: 实际上,在AngularJS中,依赖注入使用“最后获胜”规则。因此

  • 单元测试 单元测试仅依赖于源代码,是测试代码逻辑是否符合预期的最简单方法。 运行所有的单元测试 make test 仅测试指定的package # 单个package make test WHAT=./pkg/api # 多个packages make test WHAT=./pkg/{api,kubelet} 或者,也可以直接用go test go test -v k8s.io/kubernet

  • 我正在尝试使用Jmeter测试一个soap服务。当使用SOAP/XML-RPC请求元素时,服务给出正确的结果。当使用Fiddler执行时,它给出正确的响应(响应代码200)。 但是当我使用Http Request在Jeter上运行相同的服务时。它返回响应代码为500并给出 “请求格式无效:文本/xml。 这在响应数据中。我试着把它改成许多格式,像“应用程序/xml”等等,但是没有用。 [HTTP_

  • 问题内容: 我正在尝试测试AngularJS服务,但似乎不起作用。 谁能解释为什么响应为空? 问题答案: 试试这个: 请求返回的响应对象在属性(docs)中具有响应数据。