javascript - 如何测试 angularjs 指令以监视函数调用?

标签 javascript unit-testing angularjs jasmine

下面的代码执行但提示 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 });
                });
            });
        }
    }
})

Jasmine 测试:

'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.

最佳答案

更新:

我无法解决您的具体问题。主要是因为我无法让 angular-seed 继续运行/它要花很长时间,但我想我会让我的答案更完整。

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

  1. 监视一个函数,而不是被某些人触发的函数 事件/中介
  2. 在创建对象之前监视函数的原型(prototype)。换句话说:spyOn(MyObjectNamespace.Class.prototype, 'functionToSpyOn')

之后只需恢复即可,您应该没问题。


我对angular只是隐隐约约的熟悉,但是遇到过类似的问题。

方案一

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

解决方案2

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

测试:

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 与 Jasmine 一起使用。 Sinon 有一个 spy.restore 函数,可以帮你去掉第一行和最后一行。在我自己的测试中,我将第一行和 spy 创建放在 beforeEach 中,将恢复放在 afterEach 中。

关于javascript - 如何测试 angularjs 指令以监视函数调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15720072/

相关文章:

javascript - 转换 JavaScript 书签以便与 Greasemonkey 一起使用?

javascript 函数冲突或 css 选择冲突

javascript - 时刻根据日期将时间分成 block

unit-testing - Qt、单元测试和模拟对象

angularjs - Angularjs Bootstrap 模式窗口,在ok()上保存事件并更新父范围的事件列表

javascript - 如何将 csrf_token 传递给 django 中的 javascript 文件?

android - Robolectric 不执行 Runnable

java - void 方法应使用哪个测试替身

javascript - 从子 Controller 获取表单状态到父 Controller

javascript - AngularJS:如何修复范围覆盖?