为什么在浏览器不测试AngularJS应用程序时测试失败?

时间:2015-03-29 05:28:01

标签: javascript angularjs unit-testing google-chrome phantomjs

我尝试测试AngularJS 1.3.15代码的最后几天。今天它让我疯狂地给我错误,我无法在普通的GUI浏览器上重现。

第一个问题是$routecurrent属性。控制器如下:

...
.controller('HomeCtrl', ['$route', function($route) {
    var user = $route.current.locals.user;
...

上述操作会在测试时抛出错误,但会注意到浏览器会出现任何错误。

测试输出

在Chrome中它失败了!

Chrome 41.0.2272 (Linux) Controller: HomeCtrl $controller.user should have an user FAILED
    TypeError: Cannot read property 'locals' of undefined
        at new <anonymous> (/home/lucio/chatbeats/app/app.js:26:28)

在PhantomJS中它失败了!

PhantomJS 1.9.8 (Linux) Controller: HomeCtrl $controller.user should have an user FAILED
    TypeError: Cannot read property 'locals' of undefined
        at new <anonymous> (/home/lucio/chatbeats/app/app.js:26:28)

浏览器输出

在Chrome中它可以正常工作!

renders page correctly

在Firefox中它可以工作!

renders page correctly

在Chromium中它起作用了!

renders page correctly

第二个问题是$scope。要检查上一个问题是否是由处理不当的异步调用引起的(如上所述here),我已尝试使用$scope.$on设置一个侦听器:

...
.controller('HomeCtrl', ['$scope', '$route', function($scope, $route) {
    $scope.$on('$routeChangeError', function() {
      console.log($route.current);
    });
...

测试套件在浏览器显示时无法识别$scopeProvider

测试输出

在Chrome中它失败了!

Chrome 41.0.2272 (Linux) Controller: HomeCtrl $controller.user should not have the user signed in FAILED
    Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope <- HomeCtrl
    http://errors.angularjs.org/1.3.15/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope%20%3C-%20HomeCtrl

在PhantomJS中它失败了!

PhantomJS 1.9.8 (Linux) Controller: HomeCtrl should do something FAILED
    Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope <- HomeCtrl

浏览器输出

在Chrome中它可以正常工作!

prints the object to console

在Firefox中它可以工作!

prints the object to console

在Chromium中它起作用了!

prints the object to console

注意:我在同一个grunt任务下运行了两个应用程序,这意味着两个应用程序同时运行

正在使用的工具:

  • Jasmine v2.2.0
  • Karma v0.12.32
  • PhantomJS 1.9.8(Linux)(用于CLI的单元测试)
  • Chrome 41.0.2272(从CLI进行单元测试)
  • Chrome版本42.0.2311.90(64位)(用于从GUI手动测试)
  • Chromium版本41.0.2272.76 Ubuntu 14.10(64位)(用于从GUI手动测试)
  • Firefox版本37.0.2(用于从GUI手动测试)

您可以从here查看整个项目。

如果我在代码上遗漏了某些内容,请纠正我。

为什么会这样?有没有办法避免手动测试AngularJS应用程序?

1 个答案:

答案 0 :(得分:1)

$路线

单元测试通常与路由无关,因此您看到的文档和大多数示例都不包括测试运行器中的angular-route.js。这意味着$ route服务将不存在于被测试的应用程序中(因此未定义)。因此,当您实例化一个以$ route作为依赖关系的控制器时,您需要提供一个模拟对象作为依赖关系,以模拟当前的路由状态。

$controller('HomeCtrl', {
    $route: {
        current: {
            locals: {
                user: { name: 'someUser' }
            }
        }
    }
});

$范围

当角度在浏览器中运行正常应用程序期间为您实例化控制器时,控制器与之关联的范围将自动为您决定。在测试中,由于您自己创建控制器,因此您还需要自己创建并将控制器分配给控制器。您可能在文档中遇到以下内容。这只是创建一个新的作用域作为$ rootScope的子作用域,并将其作为控制器的依赖项传递。您直接使用新范围而不是$ rootScope,以便您的测试不会污染$ rootScope(也称为全局范围)。

var scope = $rootScope.$new();

$controller('HomeCtrl', {
    $scope: scope
});

结合两者:

var scope = $rootScope.$new();

$controller('HomeCtrl', {
    $scope: scope,
    $route: {
        current: {
            locals: {
                user: { name: 'someUser' }
            }
        }
    }
});