【问题标题】:angularjs test verify that event is caughtangularjs 测试验证事件是否被捕获
【发布时间】:2014-12-02 01:29:52
【问题描述】:

我最近开始学习如何使用 karma/jasmine 进行 Angular 测试。

这是场景: 我有一个监听事件的指令,当调用它时,它会调用指令范围内的一个函数。

这是我的测试。问题是该函数从未被调用。下面的代码不起作用,因为 spy 找不到侦听器调用的函数。指令函数更新 listItems 值。不是很 TDD,但目前它只在现实中有效,而不是在测试中:/

指令

(function() {
    angular.module('app').directive('listComponent', function(utilities) {
        return {
            restrict: 'E', //element
            templateUrl: 'views/listComponent.html',
            scope: {
                listItems: '='
            },
            replace: true,
            link: function (scope, element, attributes) {
                scope.title = attributes["title"];
                scope.listItemsGrouped = [];
                var primary = attributes["primaryField"];

                var itemsGrouped = _.groupBy( scope.listItems, function (obj) {
                    return obj[primary];
                });

                scope.listItems = [];
                angular.forEach(itemsGrouped[3016],function(item){
                    scope.listItems.push({dimValueParent: item.dimValueParent,dimValueChild: item.dimValueChild, value: item.value});
                });

                scope.$on('refreshListItems',
                    function(evt,affectedValues) {
                        scope.refreshList(affectedValues);
                    });

            },
            controller: function($scope){
                $scope.refreshList = function(vals) {
                    //handle values affected by the update
                    angular.forEach(vals, function(affectedValue) {
                        var indexParent = utilities.findIndexOf($scope.listItems,"dimValueParent",affectedValue.Dimensions[0].Value);
                        var indexChild = utilities.findIndexOf($scope.listItems,"dimValueChild",affectedValue.Dimensions[1].Value);
                        if (indexParent > -1 && indexChild > -1) {
                            $scope.listItems[indexChild].value = affectedValue.CalculatedValue;
                        }
                    });
                }
            }
        }
    });
}());

测试代码,在每个之前

beforeEach(inject(function ($compile, $rootScope) {
        scope = $rootScope;
        localScope = $rootScope.$new();
        ele = angular.element(
            '<list-component title="Testing generic list" list-items="list" ></list-component>'
        );

        mockupDataFactory = konstruktMockupData.getInstance();

        //these variables are needed.
        scope.data = mockupDataFactory.pivotedData;

        scope.listItems = [
            {dimValueParent: "3016",dimValueChild: "100", value:101},
            {dimValueParent: "3016",dimValueChild: "110", value:102},
            {dimValueParent: "3016",dimValueChild: "120", value:103}];

        scope.affectedValues = [
            {CalculatedValue: 1000,Dimensions:[{ Key: "1", Value: "3016" }, { Key: "4", Value: "100" }]},
            {CalculatedValue: 1100,Dimensions: [{ Key: "1", Value: "3016" }, { Key: "4", Value: "110" }]},
            {CalculatedValue: 1200,Dimensions: [{ Key: "1", Value: "3016" }, { Key: "4", Value: "120" }]}];

        scope.$apply();

    }));

这是失败的测试

 it('Should handle an update listItems event', inject(function (){
        var affectedAccountsAfterUpdateExpcted = [
            {dimValueParent: "3016",dimValueChild: "100", value:1000},
            {dimValueParent: "3016",dimValueChild: "110", value:1100},
            {dimValueParent: "3016",dimValueChild: "120", value:1200}];


        //spyOn(localScope, "refreshList");
        scope.$broadcast("refreshListItems", scope.affectedValues);

        spyOn(scope, "$on").andCallFake(function (event, affectedValues) {
            expect(affectedValues).toBe(scope.affectedValues);
            expect(event).toEqual("refreshListItems");
        });

        expect(scope.$on).toHaveBeenCalled();

        scope.$apply();
        expect(scope.listItems).toBeDefined();
        //expect(scope.listItems).toEqual(affectedAccountsAfterUpdateExpcted);
    }));

我正在为下一步该做什么而苦苦挣扎。这是基于 lght 回答的更新。如何修复以使事件在测试中被捕获?似乎没有调用 spy on。奇怪,我在直播活动!?

【问题讨论】:

  • 我没有尝试检查事件是否被捕获,而是通过模拟$on来检查范围是否正在侦听特定事件
  • 好的,有例子吗?
  • 由于您在$on 上添加了间谍,因此您不应再广播您的活动。否则,您应该监视指令的范围,而不是 $rootScope
  • 好的。我现在将范围更改为 $rootScope.new()。我正在从父范围广播并监视本地范围。 scope.$parent.$broadcast("refreshListItems",scope.affectedValues);spyOn(scope, "$on").andCallFake(function (event, affectedValues){});scope.$apply();``expect(scope.$on).toHaveBeenCalled();
  • 我仍然收到一条错误消息,提示“预期 spy $on 已被调用”

标签: angularjs unit-testing tdd karma-runner


【解决方案1】:

不要spyOn,您需要做的只是broadcast 事件,其余的应该自动完成。

it('should call the event', () => {
  spyOn(scope, 'refreshList');
  scope.$broadcast('refreshListItems');
  expect(scope.refreshList).toHaveBeenCalled();
});

【讨论】:

    【解决方案2】:

    我没有尝试检查事件是否被捕获,而是通过模拟 $on 来检查范围是否正在侦听特定事件

    describe("Testing the initialization", function () {
      beforeEach(function () {
        controller = $controller("connectionBannerCtrl", {
          $rootScope: $rootScope,
          $scope: $scope,
          ConnectionBanner: ConnectionBanner
        });
      });
      it("should subscribe to the 'ConnectionBannerChanged' event", function () {
        spyOn($rootScope, "$on").andCallFake(function (event, callback) {
          expect(callback).toBe($scope.setup);
          expect(event).toEqual("ConnectionBannerChanged");
        });
        controller = $controller("connectionBannerCtrl", {
          $rootScope: $rootScope,
          $scope: $scope,
          ConnectionBanner: ConnectionBanner
        });
        expect($rootScope.$on).toHaveBeenCalled();
      })
    });
    

    这都是关于spyOn (http://jasmine.github.io/2.0/introduction.html#section-Spies)

    【讨论】:

    • 我尝试了类似上面的方法但没有运气...请参阅我修改后的问题。看来Spy on 没有被调用
    猜你喜欢
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-06-16
    • 2019-03-20
    相关资源
    最近更新 更多