8

A newbie Jasmine/Angular question.

I have a named function within a controller like so:

.controller( 'DummyCtrl', function DummyCtrl($scope){
   var doSomething = function() {
      return "blah";
   };
})

I need to test this function, and am trying to by calling the following Jasmine spec:

describe ('myApp', function(){
  var $scope, $controller;
  var DummyCtrl;

  beforeEach(module('myApp'));

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

    describe( 'DummyCtrl', function(){
            var blah;

            beforeEach(function(){
                blah = DummyCtrl.doSomething();
            });

            it('should do something', function(){
                expect(blah).toContain("blah");
            });
    });
  });
});

Instead of things working out, I result in the following error: TypeError: Object #<DummyCtrl> has no method 'doSomething'. I'm assuming this is something super simple that I'm not understanding.

2 Answers 2

18

The function DummyCtrl you are providing for the controller registration will be used by Angular as a constructor. If you need the controller instance to expose the function doSomething without attaching it to the $scope, you should attach it to this.

Try changing

var something = function(...

to

this.something = function(...

and your test should work.

You can see this approach here: http://jsfiddle.net/yianisn/8P9Mv/. Also have a look at this SO question: How to write testable controllers with private methods in AngularJs?

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

1 Comment

this should be marked as the answer. The other one doesn't do the problem fully.
5

In a sense, using functions like that is private, and cannot be accessed from outside the function. Take a look at this link: http://javascript.crockford.com/private.html

Essentially what is said is that have a function/object in javascript, anything with a this. prefix is public, and anything with a var prefix is private.

For Angular, you can definitely have private variables and functions, if not just to lessen the memory usage of the $scope variable. Private functions should be called by your $scope objects to get values to be displayed/used by the user. Try changing it to this:

.controller( 'DummyCtrl', function DummyCtrl($scope){
   var doSomething = function() {
      return "blah";
   };
   $scope.something=doSomething();
})

And then testing the private function with:

describe( 'DummyCtrl', function(){
    var scope = {},
        ctrl = new DummyCtrl(scope);
    it('should do something', function(){
        expect(scope.something).toMatch('blah');
    });
});

1 Comment

that did the trick. I was hoping I could call these private functions to streamline some unit tests (on $scope functions that call these methods). But I'm sure I can figure out a way to do it using what calls them.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.