最佳实践:单元测试中的$ rootScope或child $ scope?

时间:2014-05-20 10:03:20

标签: angularjs unit-testing karma-runner

我在单位测试中使用基本模式(使用karma / jasmine运行)用于我的角度组件,我无法确定我的解决方案是否比我的同事建议的解决方案更安全或过度:

TL; DR:在单元测试中直接使用$ rootScope的优缺点是什么(仅限!)?

这是我目前的模式:

describe('component', function() {
  var $scope;

  beforeEach(module('myModule'));

  beforeEach(inject(function($rootScope) {
    $scope = $rootScope.$new();
    //working with it now
    $scope.foo = 'fooValue';
    $scope.$digest();
  }));

  afterEach(function() {
    $scope.$destroy();
  });

  describe('subcomponent', function() {
    it('should do something', function() {
      //arrange
      //act
      //assert
    });
  });
});

我的同事建议使用:

$scope = $rootScope;

而不是

$scope = $rootScope.$new();

会更简单,没有任何副作用,因为inject会在每个规范之前创建一个新的$injector,从而提供一个新的,干净的$rootScope

那么,这两种解决方案的好处/风险可能是什么?

Nota bene:在我们的应用中,我们始终避免直接使用$rootScope

2 个答案:

答案 0 :(得分:10)

在大多数情况下,直接在$rootScope上进行测试应该可以正常工作。但是,如果您正在测试的组件注入$rootScope,则会发生以下奇怪现象:

  • 如果您正在测试指令,那么:element.scope() === $rootScope
  • 如果您正在测试控制器,则:$scope === $rootScope

(假设你没有模仿$rootScope,以上情况属实)。 始终通过$rootScope.$new()实例化子范围,这是一项安全措施,实施成本很低。

另请注意,$rootScope$rootScope.$new()不是同一的实例,但在实践中,这似乎不是单元测试中的问题...

$rootScope 对象:

$rootScope

$rootScope.$new()

创建的子范围对象

$rootScope.$new()

$rootScope.$new(true) 创建的子级隔离范围对象:

$rootScope.$new(true)

答案 1 :(得分:4)

我怀疑其中没有多少内容。我所知道的$rootScope和子$scope之间唯一的实际差异是$parent null $rootScope。使用$parent可能非常脆弱,所以我不推荐它。

所以作为第一个停靠点,我会使用

$scope = $rootScope;

如果您的组件依赖于$parent不为空,则测试应该失败,您可以决定是否更改要使用的测试

$scope = $rootScope.$new();

或将组件更改为不依赖于$parent