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

时间:2022-11-28 08:59:01

I use a basic pattern in my unit tests (running with karma/jasmine) for my angular components and I do not manage to establish if my solution is safer or overkill than the one suggested by my coworkers:

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

TL;DR: What are the pros/cons of working with $rootScope directly in unit tests (only!)?

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

Here's my current pattern:

这是我目前的模式:

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
    });
  });
});

And my coworkers suggest that using:

我的同事建议使用:

$scope = $rootScope;

instead of

代替

$scope = $rootScope.$new();

would be simpler with no side-effect since inject creates a new $injector before each spec which provides a new and clean$rootScope.

会更简单,没有副作用,因为在每个规范之前,inject会创建一个新的$ inject,它提供了一个新的,干净的$ rootScope。

So, what could be the benefits / risks of these two solutions?

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

Nota bene: In our apps, we always avoid using $rootScope directly.

Nota bene:在我们的应用程序中,我们总是避免直接使用$ rootScope。

2 个解决方案

#1


9  

Testing directly on the $rootScope should work just fine in most cases. However, if the component that you are testing injects $rootScope then the following weirdness happens:

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

  • If you're testing a directive, then: element.scope() === $rootScope
  • 如果您正在测试指令,那么:element.scope()=== $ rootScope
  • If you're testing a controller, then: $scope === $rootScope
  • 如果您正在测试控制器,那么:$ scope === $ rootScope

(The above is true assuming you don't mock $rootScope). Always instantiating a child scope via $rootScope.$new() as you've been doing is a safety measure which costs little to implement.

(假设您没有模拟$ rootScope,以上情况属实)。始终通过$ rootScope实例化子范围。$ new()正如您所做的那样,是一种安全措施,实施成本很低。

Also keep in mind that $rootScope and $rootScope.$new() are not instances of the same class, although in practice this hardly seems to be an issue in unit testing...

还要记住$ rootScope和$ rootScope。$ new()不是同一个类的实例,尽管在实践中这似乎不是单元测试中的问题......

The $rootScope object:

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

The child scope object created by $rootScope.$new():

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

The child isolated scope object created by $rootScope.$new(true):

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

#2


4  

I suspect there isn't much in it. The only practical difference between the $rootScope and child $scopes that I know of, is that $parent is null on $rootScope. Using $parent can be quite brittle, and so I wouldn't recommend it.

我怀疑其中没有太多东西。我知道$ rootScope和子$ scope之间唯一的实际区别是$ rootScope上的$ parent为null。使用$ parent可能非常脆弱,因此我不推荐它。

So as a first port of call, I would use

所以作为第一个停靠港口,我会用

$scope = $rootScope;

If your component depends on $parent being not null, the test should fail, and you can decide whether to change the test to use

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

$scope = $rootScope.$new();

or change the component to not depend on $parent.

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

#1


9  

Testing directly on the $rootScope should work just fine in most cases. However, if the component that you are testing injects $rootScope then the following weirdness happens:

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

  • If you're testing a directive, then: element.scope() === $rootScope
  • 如果您正在测试指令,那么:element.scope()=== $ rootScope
  • If you're testing a controller, then: $scope === $rootScope
  • 如果您正在测试控制器,那么:$ scope === $ rootScope

(The above is true assuming you don't mock $rootScope). Always instantiating a child scope via $rootScope.$new() as you've been doing is a safety measure which costs little to implement.

(假设您没有模拟$ rootScope,以上情况属实)。始终通过$ rootScope实例化子范围。$ new()正如您所做的那样,是一种安全措施,实施成本很低。

Also keep in mind that $rootScope and $rootScope.$new() are not instances of the same class, although in practice this hardly seems to be an issue in unit testing...

还要记住$ rootScope和$ rootScope。$ new()不是同一个类的实例,尽管在实践中这似乎不是单元测试中的问题......

The $rootScope object:

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

The child scope object created by $rootScope.$new():

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

The child isolated scope object created by $rootScope.$new(true):

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

#2


4  

I suspect there isn't much in it. The only practical difference between the $rootScope and child $scopes that I know of, is that $parent is null on $rootScope. Using $parent can be quite brittle, and so I wouldn't recommend it.

我怀疑其中没有太多东西。我知道$ rootScope和子$ scope之间唯一的实际区别是$ rootScope上的$ parent为null。使用$ parent可能非常脆弱,因此我不推荐它。

So as a first port of call, I would use

所以作为第一个停靠港口,我会用

$scope = $rootScope;

If your component depends on $parent being not null, the test should fail, and you can decide whether to change the test to use

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

$scope = $rootScope.$new();

or change the component to not depend on $parent.

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