Joel
Joel

Reputation: 460

Using Jasmnie's spyOn on $scope.$broadcast

Im using jasmine's spyOn function to try to determine if $scope.$broadcast have been called or not.

girlnames.spec.js -the controller

describe('Girl names controller', function() {
    var vm,
        $scope;

    beforeEach(module('nameStats'));

    beforeEach(inject(function($controller, $rootScope, $q, _$httpBackend_, _namesService_) {
        vm = $controller('girlNames', {
            $scope: $rootScope.$new()
        });

        $scope = $rootScope.$new()

    }));


    it('addPersonManually should trigger $scope.$broadcast', function() {
        spyOn($scope, '$broadcast').and.callThrough()
        vm.addPersonManually(p)
        $scope.$digest();
        expect($scope.$broadcast).toHaveBeenCalled()
    });

});

girlnames.js - the controller

    "use strict";

    angular.module('nameStats').controller('girlNames', girlNames);

    girlNames.$inject = ['$scope', 'namesService'];

    function girlNames($scope, namesService) {
        var vm = this;

        vm.addPersonManually = addPersonManually;

        function addPersonManually(person) {
            $scope.$broadcast('personSelected', person);

        }
}   

The output in the console:

Expected spy $broadcast to have been called.

Upvotes: 1

Views: 592

Answers (1)

Dennis Baizulin
Dennis Baizulin

Reputation: 1420

Take a closer look at the way you are instantiating your controller

beforeEach(inject(function($controller, $rootScope, $q, _$httpBackend_, _namesService_) {
    vm = $controller('girlNames', {
        $scope: $rootScope.$new()
    });

    $scope = $rootScope.$new();
}));

You inject one scope instance and use a totally different one for testing.

Your code should look like this

beforeEach(inject(function($controller, $rootScope) {
    $scope = $rootScope.$new();

    vm = $controller('girlNames', {
        $scope: $scope
    });
}));

Advanced tip

Consider getting rid of local variables in your tests. Karma keeps references to all the test suits until all of them finish running thus causing a huge memory consumption. It can even cause process to fail if you have enough tests (it was a couple thousands in our case). Useful article.

Use this instead

beforeEach(inject(function($controller, $rootScope) {
    this.$scope = $rootScope.$new();

    this.ctrl = $controller('girlNames', {
        $scope: $scope
    });
}));

it('addPersonManually should trigger $scope.$broadcast', function() {
    spyOn(this.$scope, '$broadcast').and.callThrough()
    this.ctrl.addPersonManually(p)
    this.$scope.$digest();
    expect(this.$scope.$broadcast).toHaveBeenCalled()
});

Upvotes: 1

Related Questions