【问题标题】:How do I inject $rootScope into an AngularJS unit test?如何将 $rootScope 注入 AngularJS 单元测试?
【发布时间】:2013-03-14 17:21:19
【问题描述】:

假设我有一个依赖于 $rootScope 中的值的服务,如以下(普通)服务:

angular.module('myServices', [])
.factory('rootValGetterService', function($rootScope) {
    return {
        getVal: function () {
            return $rootScope.specialValue;
        }
    };
});

如果我想通过在 $rootScope 中输入一个值来进行单元测试,最好的方法是什么?

【问题讨论】:

    标签: javascript unit-testing dependency-injection angularjs jasmine


    【解决方案1】:
    ...
    var $rootScope;
    beforeEach(inject(function(_$rootScope_) {
      $rootScope = _$rootScope_;
    }));
    ...
    

    【讨论】:

    • 这不是为每个测试提供相同的范围吗?您如何将新的范围传递给服务?
    • 嗨 Tamlyn,您的根范围在什么方面不再新鲜?我相信我只用它来广播事件。
    • 下划线是必需的,否则在闭包中的$rootScope$rootScope 参数之间存在命名冲突。
    • @Tamlyn 这个为每个测试提供了一个新的隔离 $rootScope。如果有人不喜欢下划线约定,可以这样写beforeEach(inject($injector => { $rootScope = $injector.get('$rootScope'); }))
    【解决方案2】:

    通过使用provide(),你可以注入一个新的$rootScope:

    describe('in rootValGetter', inject(function ($rootScope) {
        var scope;
        var testRootValGetter;
    
        beforeEach(function () {
    
            scope = $rootScope.$new();
    
            module(function ($provide) {
                $provide.value('$rootScope', scope);
            });
    
            inject(function ($injector) {
                testRootValGetterService = $injector.get('rootValGetterService');
            });
        });
    
        it('getVal returns the value from $rootScope', function() {
            var value = 12345;
    
            scope.specialValue = value;
    
            expect(testRootValGetterService.getVal()).toBe(value);
        }
    }
    

    【讨论】:

    • 这种模式对我不起作用。 Angular 不断抛出此错误:“错误:注入器已创建,无法注册模块!”
    • 为什么要使用scope = $rootScope.$new();,而不是直接使用$rootScope
    • 要拥有一个干净的 $rootScope,您可以尝试从 beforeEach 注入它:beforeEach(inject(function($rootScope) {
    • 如果你把它放在顶级描述中,有谁知道为什么会发生这种情况?花了一段时间向后工作,找出我从哪里得到这个错误。
    【解决方案3】:

    包含angular-mocks.js,然后使用angular.mock.inject

    【讨论】:

      【解决方案4】:

      您可以将所需的属性直接模拟到 $rootScope 中,而不是像注入 $scope 那样创建新范围。

      然后$rootScope 将被注入您正在测试的代码中可用的那些属性。

      至少这是我解决相同问题的方法。

      以下代码应该可以在您的示例中使用。

      beforeEach(inject(function($rootScope) {
          $rootScope.specialValue = 'whatever';
      }));
      

      【讨论】:

        【解决方案5】:

        试着给出更详细的答案,包括测试用例:

        ...

        var $rootScope;
        beforeEach(inject(function(_$rootScope_) {
          $rootScope = _$rootScope_;
        }));
        

        ...

          it('getVal returns the value from $rootScope', function() {
                var value = 12345;
                $rootScope.specialValue = value;
                expect(testRootValGetterService.getVal()).toBe(value);
            }
        

        【讨论】:

          【解决方案6】:

          这就是我所做的:

          it('some kind of wacky test', function($rootScope, Translate){
              $rootScope.lang = 'en';
              expect(Translate('overview').toBe('Overview');
          }
          

          【讨论】:

            【解决方案7】:

            希望这对其他人有所帮助,因为这是解决类似问题的方法。

            var rootValGetterService;
            
            beforeEach(inject(function($rootScope,$injector) {
                $rootScope.specialValue = "test";
                rootValGetterService= $injector.get('rootValGetterService');
            }));
            
            it("Should have a service", function () {
                expect(rootValGetterService).toBeDefined();
            });
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-02-16
              • 1970-01-01
              • 2012-05-20
              相关资源
              最近更新 更多