【问题标题】:How to unit test spy on $emit in a directive?如何在指令中对 $emit 进行单元测试?
【发布时间】:2014-08-05 21:14:11
【问题描述】:

如何检查是否在指令的单元测试中调用了 $emit?

我的指令相当简单(为了说明):

angular.module('plunker', [])
.directive('uiList', [function () { 
    return {
        scope: {
            lengthModel: '=uiList',
        },
        link: function (scope, elm, attrs) {
            scope.$watch('lengthModel', function (newVal) {
                        scope.$emit('yolo');
            });
        }
    }
}])

所以每次 uiList 属性发生变化时,都会发出事件。

我的单元测试代码如下:

describe('Testing $emit in directive', function() {
  var scope;
  var element;


  //you need to indicate your module in a test
    beforeEach(function () {
        module('plunker');
        inject(function ($rootScope, $compile) {
            scope = $rootScope.$new();
            scope.row= 1;
            spyOn(scope,'$emit');
        element = angular.element('<ul id="rows" ui-list="row">');
        $compile(element)(scope);
        });
    });

  it('should emit', function() {

    scope.$digest();
    scope.row = 2;
    scope.$digest();
    expect(scope.$emit).toHaveBeenCalledWith("yolo");
  });
});

这总是会给我一个错误,说明 scope.$emit 从未被调用过。 范围有问题吗?有人可以帮忙吗?

Plunker:http://plnkr.co/edit/AqhPwp?p=preview

【问题讨论】:

    标签: angularjs unit-testing angularjs-scope karma-runner karma-jasmine


    【解决方案1】:

    你的指令创建了一个独立的范围,它调用$emit,所以你需要监视这个;)

    describe('Testing $emit in directive', function() {
      var scope;
      var element;
      var elementScope;
    
      beforeEach(module('plunker'));
    
      beforeEach(inject(function($rootScope, $compile) {
          scope = $rootScope.$new();
          scope.row = 1;
          element = angular.element('<ul id="rows" ui-list="row">');
          $compile(element)(scope);
          scope.$digest();
          elementScope = element.scope();
      }));
    
      it('should emit', function() {
        // arrange
        spyOn(elementScope, '$emit');
    
        // act
        scope.$apply(function() {
          scope.row = 2;
        });
    
        // assert
        expect(elementScope.$emit).toHaveBeenCalledWith("yolo");
      });
    });
    

    Fixed plunker here :)

    【讨论】:

    • 赞成在一个很好的答案中讽刺地使用 yolo 这个词
    【解决方案2】:

    我不确定 glepetre 是如何工作的(不确定它是否真的有效)。对我来说没有。问题是该指令在传入范围内运行$new,因此它在内部创建的范围和element.scope() 有所不同。您可以查看他们的$id 字段。因此,窥探您从element.scope() 获得的范围无济于事。我遇到了 smilar 问题,不得不做一些小技巧来让它工作。

    我的测试来了:

        beforeEach(inject(function () {
            scope = $rootScope.$new();
    
            scope.$apply(function () {
                scope.field = null;
                scope.name = 'nolength';
            });
    
            spyOn(scope, '$new').and.returnValue(scope);
            spyOn(scope, '$emit');
    
            var element = angular.element('<my-directive name="name" field="field" title="\'Title\'" ></my-directive>');
            noLengthValidation = $compile(element)(scope);
    
            scope.$apply();
            elementScope = element.scope();
        }));
    

    所以诀窍是在scope 上模拟$new 函数,这样它就不会在幕后创建一个新的范围并将事情搞砸,它会自行返回!这是测试本身:

        it('The directive should not react on string length if no max-chars attribute presented', function () {
            scope.$apply();
            noLengthValidation.isolateScope().field = 'fieldisssssssveeeeerryyyyyylooooooonnnngggggggggggggggggggggggggggg';
            scope.$apply();
            expect(scope.$emit).toHaveBeenCalledWith('ON_MORE_AWASOME_EVENT', 'nolength');
        });
    

    以及指令中调用$emit 的部分。以防万一:

            function validate() {
                scope.validate = 1;
                if (scope.field) {
                    if (!isValid()) {
                        scope.$emit('ON_AWASOME_EVENT', {code : scope.name, text : 'Field ' + scope.title + '  is feels bad'});
                    } else {
                        scope.$emit('ON_MORE_AWASOME_EVENT', scope.name);
                    }
    
                }
            }
    

    【讨论】:

      猜你喜欢
      • 2016-07-25
      • 2017-08-08
      • 1970-01-01
      • 1970-01-01
      • 2013-06-26
      • 2020-02-29
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      相关资源
      最近更新 更多