11

下面的代码执行但抱怨 element.popover 没有被调用。我似乎无法弄清楚问题是什么。

提前感谢您的帮助。

指示:

angular.module('directives', []).

directive('popOver', function ($http) {

    return {
        restrict:'C',

        link: function (scope, element, attr) {
            element.bind('mouseover', function (e) {
                $http.get("someurl" + attr.chatid + ".json").success(function (data) {
                    element.popover({content: data.firstName + " " + data.lastName });
                });
            });
        }
    }
})

茉莉花测试:

'user strict'

describe('directives', function() {
    beforeEach(module('directives'));
    describe('popOver', function() {
    var $scope, compile, location,  $httpBackend, elm;

    beforeEach(inject(function($rootScope, $compile, _$httpBackend_) {
        $scope = $rootScope.$new();
        compile = $compile;
        $httpBackend = _$httpBackend_;
        elm = angular.element('<i class="pop-over" data-placement="top" data-chatid="testChatId" > </i>');
        compile(elm)($scope);

    }));

    it('should call element.popover()', function() {
        $httpBackend.expectGET('someurl/testChatId.json').
            respond([ {firstName: 'test', lastName: 'user'}]);

        spyOn(elm, 'popover').andCallThrough();

        elm.trigger('mouseover');
        $httpBackend.flush();

        expect(elm.popover).toHaveBeenCalled();
    });
  });
});

输出:

Chrome 26.0 (Mac) directives popOver should call element.popover() FAILED
Expected spy popover to have been called.
Error: Expected spy popover to have been called.
4

2 回答 2

8

更新:

我无法解决您的具体问题。主要是因为我无法获得角种子/它需要永远,但我认为我会让我的答案更完整。

一般有两种方法可以解决这个问题:

  1. 监视由某些事件/中介触发的功能以外的功能
  2. 在创建对象之前窥探函数的原型。换句话说:spyOn(MyObjectNamespace.Class.prototype, 'functionToSpyOn')

之后只是恢复,你应该没问题。


我对角度只是模糊熟悉,但遇到过类似的问题。

解决方案 1

您可以只分离出函数而不是匿名指定它。这有助于专门测试您的功能并避免所有有角度的东西。

解决方案 2

有时使用框架这是不可能的。这里的主要问题是您的间谍附加自身太晚,并且引用丢失或被覆盖。

测试:

describe('directives', function() {
    beforeEach(module('directives'));
    describe('popOver', function() {
    var $scope, compile, location,  $httpBackend, elm;

    beforeEach(inject(function($rootScope, $compile, _$httpBackend_) {
        $scope = $rootScope.$new();
        compile = $compile;
        $httpBackend = _$httpBackend_;
        elm = angular.element('<i class="pop-over" data-placement="top" data-chatid="testChatId" > </i>');
        compile(elm)($scope);

    }));

    it('should call element.popover()', function() {
        var popoverFunction = $.fn.popover;
        $httpBackend.expectGET('someurl/testChatId.json').
            respond([ {firstName: 'test', lastName: 'user'}]);

        spyOn($.fn, 'popover').andCallThrough();

        elm.trigger('mouseover');
        $httpBackend.flush();

        expect($.fn.popover).toHaveBeenCalled();
        //restore popover, use sinon's restore fn instead here
        $.fn.popover = popoverFunction
    });
  });
});

您可以将诗乃与茉莉花一起使用。Sinon 有一个 spy.restore 功能,可以为您摆脱第一行和最后一行。在我自己的测试中,我将第一行和间谍创建放在了 beforeEach 中,将恢复放在了 afterEach 中。

于 2013-04-09T20:38:38.857 回答
5

我让它工作。
jquery和jquery popover js文件需要在测试时在angular.js之前加载。此顺序应在 testacular.conf.js 文件中指定。此外,http 的 url 缺少“/”。这是对我有用的代码:


angular.module('directives', []).

directive('popOver', function($http) {

  return {
    restrict: 'C',

    link: function(scope, element, attr) {
      element.bind('mouseover', function(e) {
        $http.get("someurl/" + attr.chatid + ".json").success(function(data) {
          element.popover({
            content: data.firstName + " " + data.lastName
          });
        });
      });
    }
  }
})



'user strict'

describe('directives', function() {
  beforeEach(module('directives'));
  describe('popOver', function() {
    var $scope, compile, location, $httpBackend, elm;

    beforeEach(inject(function($rootScope, $compile, _$httpBackend_) {
      $scope = $rootScope.$new();
      compile = $compile;
      $httpBackend = _$httpBackend_;
      elm = angular.element('<i class="pop-over" data-placement="top" data-chatid="testChatId" > </i>');
      compile(elm)($scope);

    }));

    it('should call element.popover()', function() {
      $httpBackend.expectGET('someurl/testChatId.json').
      respond([{
        firstName: 'test',
        lastName: 'user'
      }]);
      //spyOn(elm, 'popover').andCallThrough();
      spyOn($.fn, 'popover').andCallThrough();

      elm.trigger('mouseover');
      $httpBackend.flush();

      //expect(elm.popover).toHaveBeenCalled();
      expect($.fn.popover).toHaveBeenCalled();
    });
  });
});
于 2013-04-19T15:32:26.137 回答