1

I'm trying to write unit-tests for an Angular application for the first time. Currently i'm having some problems running the tests. Running the application normally works fine, it doesn't give any errors. However, when running the tests using Karma and Jasmine i'm getting the following error:

TypeError: 'undefined' is not a function (evaluating '$scope.addActiveClassToMenuButton('menuButtonHome')')

I'm using the ui.router module. Not sure if that matters.

Parent controller

Parent controller contains the following method:

angular.module('testApp')
.controller('ParentCtrl', function ($scope, $resource) {

    $scope.addActiveClassToMenuButton = function(buttonId) {
        //Some code
    }

}

Child controller

Child controller calls the parents method like this:

angular.module('testApp')
.controller('ChildCtrl', function ($scope, $resource) {

    $scope.addActiveClassToMenuButton('menuButtonHome');

}

Child controller test file

The test file that fails:

describe('Child controller tests. ', function () {
    beforeEach(module('testApp'));

    var ChildCtrl, scope;

    beforeEach(inject(function ($controller, $rootScope) {
      scope = $rootScope.$new();
      ChildCtrl = $controller('ChildCtrl', {
        $scope: scope
      });
    }));

    it('simple false test', function () {
      expect(false).toBe(false);
    });
});

Even though i'm not using the scope in the test yet, all tests fail because the code can't find the parents method.

Solution

Changing the test file to this worked:

describe('Child controller tests. ', function () {
  beforeEach(module('testApp'));

  var controller, scope, parentScope, childScope;

  beforeEach(inject(function ($controller, $rootScope, $compile) {
    scope = $rootScope.$new();
    var el = angular.element('<div ng-controller="ParentCtrl"><div ng-controller="ChildCtrl"></div></div>');
    $compile(el)(scope);

    parentScope = el.scope();
    childScope = el.children().scope();
  }));

  it('simple false test', function () {
    expect(false).toBe(false);
  });

});

1 Answer 1

4

Try this..

describe('Child controller tests. ', function () {
    beforeEach(module('testApp'));

    var ChildCtrl, scope;

    beforeEach(inject(function ($controller, $rootScope, $compile) {
      scope = $rootScope.$new();
      var el = angular.element('<div ng-controller="ParentCtrl"><div ng-controller="ChildCtrl"></div></div>');

      $compile(el)(scope);

      // to access parent controller.
      var parentScope = el.scope();
      var childScope = el.children().scope();

      // now you should be able to access from parent and child scopes.
    }));

    it('simple false test', function () {
      expect(false).toBe(false);
    });
});

This will instantiate ParentCtrl first and then extend the scope of it with the ChildCtrl's scope.

In the example that you have given only ChildCtrl is instantiated ParentCtrl is not instantiated.

Sign up to request clarification or add additional context in comments.

4 Comments

Actually... i cheered a bit too early. The error goes away and the test succeeds. (obviously false equals false) However i seem to be unable to access anything in the scope now. A simple scope.variable is always undefined.
I have updated the post to get retrieve parent and child scopes.
The variables had to be declared outside the beforeEach() method. But after that it worked. Thanks again. :)
that's work for me :), just a question. what to do with service dependencies

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.