【问题标题】:Mocking service in AngularJS HTTPAngularJS HTTP 中的模拟服务
【发布时间】:2016-07-18 08:26:09
【问题描述】:

我正在尝试测试一个通过服务执行 http 请求的控制器。

我应该只是模拟服务并返回一个默认值,而不是执行实际的 http 请求,还是使用$httpBackend

顺便说一下,我正在 Jasmine 中进行测试。

谢谢。

【问题讨论】:

  • mockService = { getApi: function(url: string) { return "hello world"; } } createCtrl = function() { return $controller('homeCtrl', {$scope: scope, 'dataService': mockService}) };
  • 在这里你可以看到我正在尝试向我的控制器添加一个模拟服务,但是,当我在测试中调用我的控制器中的 getMessage() 方法时,它又会调用 getApi( "afdlasf") 方法在我的服务中,它似乎仍在使用真正的服务,而不是模拟的服务。任何帮助将非常感激。谢谢

标签: angularjs http mocking jasmine


【解决方案1】:

TL;DR 不要执行实际的 http 请求。

  • 单元测试
    在进行适当的单元测试时,您只测试一个单元。这可以是一个类,也可以只是一个类的一部分。这意味着您必须模拟依赖项。在您的情况下,这意味着您将模拟服务以简单地充当类。所以返回一个包含数据模型的承诺。
    pro:真正的单元测试的最大优势是速度。您可以执行大量单元测试,而不是单个端到端测试。
    缺点:单元测试的最大缺点是,当您更改依赖项以在不同的方式,您的测试仍然会成功,因为该服务已被模拟。
  • 集成测试
    集成测试几乎可以像单元测试一样工作,但在这里您不会模拟直接依赖关系。在您的情况下,在进行集成测试时,您不会模拟服务,而是模拟它的依赖项(使用 $httpBackend)。
    pro:仍然相当快,并提供更强大的测试。因为当您更新直接依赖项时,您测试的类可能会失败,因为它们没有被模拟。
    缺点:不如单元测试快,但仍然非常快。
  • 端到端
    E2E 测试测试整个应用程序,而不是模拟任何东西。这包括对 api 的所有 XHR 调用。
    pro:由于没有任何东西被模拟,它总是覆盖整个应用程序。跟踪 DOM 更改和浏览器兼容性非常有用。它甚至可以自动截取屏幕截图以提供渲染数据的真实视图。
    con:速度很慢。因为它执行实际的 API 调用,所以这些测试可能需要一段时间才能执行。

所以要回答你的问题,这取决于你在写什么。当您编写适当的单元测试时,您应该模拟服务:

$provide.service('DataService', ['$q', function($q) { 
  this.get = function() {
    return $q(function(resolve, reject) {
      if (requestFailed) {
        reject('The request failed');
      }

      resolve(APIData);
    });
  };
}]);

如果您正在进行集成测试,您应该使用 $httpBackend 模拟实际的 $http-request。

it('should request data', function() {
  $httpBackend
    .expect('GET', url)
    .respond(APIData);

  expect($scope.list.count).toEqual(0);

  $scope.clickRetrieve();
  $httpBackend.flush();

  expect($scope.list.count).toBeGreaterThan(0);
});

我正在开发一个相当大的应用程序,但没有太多的测试经验。但到目前为止,我最喜欢的测试类型是集成测试。我在单元测试方面遇到了一些问题,这些问题由于模拟服务而没有揭示出重大变化。因为我几乎已经切换到集成测试,在那里我几乎完全模拟了我的数据服务。

旁注:我使用数据服务作为我的应用程序和 API 之间的一个层,如果 API 被更新,理论上我应该只更新数据服务为 no除了存储库访问这些的类。 这样我可以确保在我的应用程序中我只使用 DataModels 而不是简单的对象,并且我使用 undefined,而不是 null

【讨论】:

    【解决方案2】:

    使用$httpBackend

    因为你还需要模拟响应

    $httpBackend.when("GET",'URL').respond(respnonse);
    

    response 包含您期望的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-07
      • 2013-01-24
      • 2015-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多