【问题标题】:Unit-testing AngularJS controller with Protractor使用量角器对 AngularJS 控制器进行单元测试
【发布时间】:2016-02-12 19:03:21
【问题描述】:

我有一个功能完善的应用程序,运行 ElectronProtractor 来进行测试。我能够对 DOM 元素进行测试,但我无法找到一种方法来测试我在控制器中拥有的功能。我收到此错误消息

失败:

1) app-controller.js 遇到声明异常
留言:
ReferenceError:未定义窗口
堆栈跟踪:
ReferenceError:未定义窗口
在对象。 (/home/yann/workspace/hacker-keyboard/node_modules/angular/angular.js:28902:4)
在需要 (module.js:384:17)
在对象。 (/home/yann/workspace/hacker-keyboard/node_modules/angular/index.js:1:63)

我查看了很多帖子,AngularJS documentation,但我还没有找到解决问题的方法。
以下是我用于测试的文件:

app.js

var app = angular.module('app', [
    'appController'
]);

var controllerModule = angular.module('appController', []);

app-controller.js

controllerModule.controller('appController', ['$scope',
    '$timeout',
    '$window',
    '$interval',
    '$filter',
    function ($scope, $timeout, $window, $interval, $filter){
    /* controller code here */
    }]);

conf.js

exports.config = {
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['test-spec.js'],
    capabilities: {
        browserName: "chrome",
        chromeOptions: {
            binary: "./dist/myApp-linux-x64/myApp"
        }
    },
    onPrepare: function () {
        browser.resetUrl = "file://";
    }
};

test-spec.js

describe('app-controller.js', function () {
    require('angular');
    require('angular-mocks');

    var scope, controller;

    beforeEach(function () {
        module('app');
    });

    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        controller = $controller("appController", {
            $scope: scope
        });
    }));

    it('should return empty string',
            function () {
                var result = scope.fooFunction(12, 'blue');
                expect(result).toEqual("");
            });
});

你们知道我错过/误解了什么吗?

编辑
因为我不在 Angular 文件中,所以我无权访问 window 对象。 angularangular-mocks 的要求导致错误,因为它无法访问 window 对象。有谁知道如何将它链接到我的 test-spec.js 文件中?

【问题讨论】:

    标签: angularjs unit-testing protractor electron


    【解决方案1】:

    我看到错误

    ReferenceError: 未定义窗口

    这个注入可能有问题?

    我给你我的工作配置文件。我使用框架 Jasmine。

    exports.config = {
    allScriptsTimeout: 55000,
    specs: ['e2e/*-spec.js'],
    framework: 'jasmine2',
    baseUrl: /*<baseUrl>*/"http://url.com"/*</baseUrl>*/ ,
    onPrepare: function() {
        var TeamCityReporter = require('jasmine-reporters').TeamCityReporter;
        jasmine.getEnv().addReporter(new TeamCityReporter());
        var disableNgAnimate = function() {
            angular.module('disableNgAnimate', []).run(['$animate', function($animate) {
                $animate.enabled(false);
                var style = ".ngdialog-content,.ngdialog-overlay,.ngdialog-closing .ngdialog-content,.ngdialog-closing .ngdialog-overlay {  animation-duration: 0ms!important;}";
                $("<style>" + style + "</style>").appendTo("head");
            }]);
        };
        browser.addMockModule('disableNgAnimate', disableNgAnimate);
    
        // Store the name of the browser that's currently being used.
        browser.getCapabilities().then(function(caps) {
            browser.params.browser = caps.get('browserName');
        });
    },
    

    };

    【讨论】:

      【解决方案2】:

      根据我使用 Angular 的经验,我实际上建议不要将 Protractor 用于您正在尝试做的事情。 Protractor 专门设计用于通过 Selenium 加载浏览器,并执行类似于人类用户可能执行的浏览器中的手动测试的测试 - 输入表单,单击“提交”,检查您所在的页面,请参阅如果警报或消息可见等。

      如果你想专门测试一个函数或控制器,你应该使用一个单元测试框架,比如 karma。 Karma 支持模拟后端调用以及控制器和模块,因此您可以在测试中隔离控制器的功能,而无需运行 selenium 或浏览器(这对于执行单元测试的功能也是不必要的)。

      不使用量角器进行单元测试的另一个原因是速度。加载和执行少量代码比启动服务器、浏览器、驱动程序、加载页面等要快得多。我有 E2E Protractor 测试套件,运行时间为 20 分钟以上。这很好 - 手动测试通过的时间更长,但时间差异也可能是一个因素。

      陷阱 测试的确切配置可能取决于您使用的 Angular 版本,因此请注意您使用的文档和示例。其次,Karma 对您加载的文件非常挑剔——您想要使用的每个供应商或应用程序文件都必须加载,并且必须在 karma.conf.js 文件中以正确的顺序加载。

      为了说明,下面是我将如何设置单元测试,就像您在 Karma 中尝试使用 Jasmine 所做的那样:

      karma.conf.js

      module.exports = function(config) {
          basePath: ‘’,
          frameworks: [‘jasmine’],
          // In Karma, you MUST load both your application files, and then after
          // your test/spec files. It doesn’t run in a browser, so it will only execute
          // code that is directly loaded.
          files: [
              // Notice the load order is required vendors, then dependencies, then the app module
              // which requires the dependencies…
              ‘js/vendor/jquery’,
              ‘js/vendor/angular’,
              ‘js/vendor/angular-mocks’,  // if you want to use angular-mocks, include it!
      
              ‘js/app-controller.js’,
              ‘js/app.js’,
          ],
      
          reporters: [‘progress’],
          port: 9876,
          colors: true,
          browsers: [‘Chrome’],
          plugins: [‘karma-jasmine’, ‘karma-chrome-launcher’],
          singleRun: true // run only once, then quit tests
      }
      

      test-spec.js

      describe(‘app-controller.js’, function() {
      
          var appController;
      
          beforeEach(function() {
              module(‘app’);
          });
      
          beforeEach(inject(function($controller) {
              appController = $controller(‘appController’);
          }));
      
          it(‘should return an empty string’, function() {
              var result = appController.fooFunction(12, 'blue');
              expect(result).toEqual("");
          })
      })
      

      第二个不是关于“窗口”无法识别的问题,它取决于测试环境的运行上下文。 “window” 是一个 JavaScript 全局变量,在浏览器内部,它总是已知的,因为它是一个内置定义。然而,在 Angular 内部,windows 没有任何意义——但 Angular 确实有一个提供程序“$window”,它提供从 Angular 应用程序中访问窗口的权限(因为您的控件注入了它,您可能已经知道这一点)。 我在您的配置中看到重置 URL 是“file://”——如果您通过 FILE 协议而不是 HTTP 加载文件,则会出现警告,浏览器不会认为运行 JavaScript,因为它认为它只是在读取文本文件。

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2013-05-01
        • 2014-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-26
        • 2012-11-19
        相关资源
        最近更新 更多