【问题标题】:Angular.js e2e test HTTP requests to external serviceAngular.js e2e 测试对外部服务的 HTTP 请求
【发布时间】:2013-11-13 10:08:11
【问题描述】:

我正在尝试对 e2e 场景中的指令进行一些基本测试。代码工作得很好 我可以将新元素呈现给浏览器。这是我正在使用的代码。

这里是指令代码。

'use strict';

var directives = angular.module('lelylan.directives', [])

directives.directive('device', ['Device', function(Device) {
  var definition = {
    restrict: 'E',
    replace: true,
    templateUrl: 'js/templates/device.html',
    scope: { id: '@' }
  };

  definition.link = function postLink(scope, element, attrs) {
    scope.$watch('id', function(value){
      var device = Device.get({ id: scope.id }, function() {
        scope.device = device;
      });
    });
  };

  return definition
}]);

这里是设备服务代码。

// Service Device
'use strict';

angular.module('lelylan.services', ['ngResource']).
  factory('Device', ['$resource', '$http', function($resource, $http) {

    var token = 'df39d56eaa83cf94ef546cebdfb31241327e62f8712ddc4fad0297e8de746f62';
    $http.defaults.headers.common["Authorization"] = 'Bearer ' + token;

    var resource = $resource(
      'http://localhost:port/devices/:id',
      { port: ':3001', id: '@id' },
      { update: { method: 'PUT' } }
    );

    return resource;
  }]);

这里是应用代码。

'use strict';

angular.module('lelylan', ['lelylan.services', 'lelylan.directives'])

这里是 index.html。

<!doctype html>
<html lang="en" ng-app="lelylan">
  <head>
    <meta charset="utf-8">
    <title>Lelylan Components</title>
    <link rel="stylesheet" href="css/app.css"/>
  </head>
  <body>

    <device id="50c61ff1d033a9b610000001"></device>

    <!-- In production use: <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script> -->
    <script src="lib/angular/angular.js"></script>
    <script src="lib/angular/angular-resource.js"></script>
    <script src="js/app.js"></script>
    <script src="js/services.js"></script>
    <script src="js/directives.js"></script>
  </body>
</html>

阅读Angular documentation 并尝试不同的解决方案后,我想出了以下 测试我在哪里尝试模拟我的后端请求。问题是请求仍然命中真正的服务。它 看起来我无法拦截请求。

// e2e test
'use strict';

describe('directives', function() {

  var resource = { id: '1', uri: 'http://localhost:3001/devices/1' };
  var myAppDev = angular.module('myAppDev', ['lelylan', 'ngMockE2E']);

  myAppDev.run(function($httpBackend) {
    $httpBackend.when('GET', 'http://localhost:3001/devices/1').respond(resource);
    $httpBackend.when('GET', /\/templates\//).passThrough();
  });

  beforeEach(function() {
    browser().navigateTo('../../app/index.html');
  });

  describe('when renders a device', function() {

    it('renders the title', function() {
      expect(element('.device .name').text()).toEqual('Closet dimmer');
    });

    it('renders the last time update', function() {
      expect(element('.device .updated-at').text()).toEqual('2012-12-20T18:40:19Z');
    })
  });
});

我想我缺少一些配置,但我无法真正理解哪些配置。 非常感谢。

【问题讨论】:

    标签: angularjs testing karma-runner


    【解决方案1】:

    阅读this question 中的最后一条评论,我得出了最终解决方案。

    实际上我错过了一个重要步骤,因为我必须使用一个使用模拟应用程序的 HTML 文件。让代码说话吧。

    1) 我用测试环境创建了一个 HTML 文件。主要区别在于我设置了 ng-app=test 并添加了两个新的 JS 文件。第一个是 /test/e2e/app-test.js,是我创建测试模块的地方,第二个是 /test/lib/angular-mocks.js。

    <!doctype html>
    <html lang="en" ng-app="test">
      <head>
        <meta charset="utf-8">
        <title>Lelylan Test</title>
        <link rel="stylesheet" href="css/app.css"/>
      </head>
      <body>
    
        <device id="1"></device>
    
        <script src="lib/angular/angular.js"></script>
        <script src="lib/angular/angular-resource.js"></script>
        <script src="js/app.js"></script>
        <script src="js/settings.js"></script>
        <script src="js/services.js"></script>
        <script src="js/controllers.js"></script>
        <script src="js/filters.js"></script>
        <script src="js/directives.js"></script>
    
        <!-- Test application with mocked requests -->
        <script src="../test/e2e/app-test.js"></script>
        <script src="../test/lib/angular/angular-mocks.js"></script>
      </body>
    </html>
    

    现在,让我们看看我们如何实现测试模块。在这里,我定义了一个与我的主模块 (lelylan) 完全相同的模块,并添加了 ngMockE2E,让您可以访问 $httpBackend 并模拟 HTTP 请求。

    'use strict';
    
    var resource = { id: '1', uri: 'http://localhost:3001/devices/1' };
    
    var test = angular.module('test', ['lelylan', 'ngMockE2E']);
    
    test.run(function($httpBackend) {
      $httpBackend.when('GET', 'http://localhost:3001/devices/1').respond(resource);
      $httpBackend.when('GET', /\/templates\//).passThrough();
    });
    

    仅此而已。运行 scripts/e2e-test.sh 就完成了。

    【讨论】:

    • 那么我需要在这个新的测试 html 文件中复制所有应用程序的现有 html 吗?有没有办法像在单元测试中一样将 $httpBackend 包含在 e2e 测试中,而不需要对实际应用进行修改?
    • 回答我自己的问题 - 如果您的所有 html 都在一个文件中并且您没有使用路由和部分模板,那么是的,您需要复制您的 html 文件以获得测试版本。您无需更改 app.js,只需添加包含 ngMockE2E 的 test-app.js。目前似乎不可能只修改scenario.js。我找到的最佳示例:github.com/stephennancekivell/angular_e2e_http/tree/ngMockE2E
    猜你喜欢
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 2015-01-09
    • 2011-08-09
    • 2018-03-02
    • 2018-08-13
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多