最近几天我一直在尝试测试 AngularJS 1.3.15 代码。今天,它给我带来了无法在普通 GUI 浏览器上重现的错误,这让我抓狂。
第一个问题是 $route 的 current
属性。 Controller 如下:
...
.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 中它可以工作!
在 Firefox 中它可以工作!
在 Chromium 中它可以工作!
第二个问题与$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 中它可以工作!
在 Firefox 中它可以工作!
在 Chromium 中它可以工作!
注意:我在同一个 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 应用程序的手动测试吗?
最佳答案
$route
单元测试通常独立于路由,因此您看到的文档和大多数示例都不在测试运行程序中包含 angular-route.js。这意味着 $route 服务不会存在于被测试的应用程序中(因此未定义)。因此,当你实例化一个以 $route 作为依赖的 Controller 时,你需要提供一个模拟对象作为依赖,以便模拟当前的路由状态。
$controller('HomeCtrl', {
$route: {
current: {
locals: {
user: { name: 'someUser' }
}
}
}
});
$范围
当 Angular 在浏览器中正常运行应用程序期间为您实例化 Controller 时,会自动为您决定与 Controller 关联的范围。在测试中,由于您自己创建 Controller ,因此还需要自己创建范围并将其分配给 Controller 。您可能在文档中遇到过以下内容。这只是创建一个新作用域作为 $rootScope 的子作用域,并将其作为 Controller 的依赖项传递。您使用新的作用域而不是直接使用 $rootScope,这样您的测试就不会污染 $rootScope(也称为全局作用域)。
var scope = $rootScope.$new();
$controller('HomeCtrl', {
$scope: scope
});
将两者结合起来:
var scope = $rootScope.$new();
$controller('HomeCtrl', {
$scope: scope,
$route: {
current: {
locals: {
user: { name: 'someUser' }
}
}
}
});
关于javascript - 为什么测试失败而浏览器不测试 AngularJS 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29325942/