How do I test variables local to an Angular controller in Jasmine

16,782

Solution 1

In your jasmine spec, first create the controller:

var ctrl;

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

Then you can access its properties by doing ctrl.pagesById. Of course, rather than doing var pagesById you'll need to use this.pagesById in your controller.

Solution 2

Here is my way for testing local variables in Angular methods:

//------- Function for getting value of local variables

function getLocalVariable(sLocalVarName, obj, method, args){
    method = method.toString();
    let changedMethod = method.substring(0, method.lastIndexOf("}")) + ";" + "return " + sLocalVarName + "}";
    eval(' changedMethod = ' + changedMethod);

    return changedMethod.call(obj, args)
}

//----------- service

class assignStuffService {

    getAvaliableStuff(shift) {
        const params = {
            agency_id: 0 ,
            start_time: shift.data.shift.start_time,
            end_time : shift.data.shift.end_time
        };
    }
}

//----------- part of spec

it('should set values to "params" object props', () => {

            let shift = {
                data:{
                    shift:{
                        start_time:'',
                        end_time:''
                    }
                }
            };

            let params = getLocalVariable('params',
                                            assignStuffService,
                                            assignStuffService.getAvaliableStuff,
                                            shift);

            expect(params).toEqual({
                agency_id: 0 ,
                start_time: shift.data.shift.start_time,
                end_time : shift.data.shift.end_time
            });

        });
Share:
16,782
akronymn
Author by

akronymn

Equal parts explorer and technologist. Lover of good design and intelligent interfaces. Consumer of APIs. Developer of the web. Builder of products. Photographer. Gourmet and gourmand. Local political junky. Serious casual gamer. Wanderer. Hobby collector.

Updated on June 23, 2022

Comments

  • akronymn
    akronymn about 2 years

    I have a controller with a local variable

    function IndexCtrl($scope) {
      var pagesById = [];
      loadPages();
    
      // snip
    
      function loadPages() {
        // pagesById gets populated
      }
    
      // snip
    }
    

    I'd like to test that pagesById is correctly populated but I'm not sure how to get at it from my it(). I don't need this variable to be in the $scope, it's just an intermediate set of information, so if I can avoid adding it to $scope that would be ideal.

    it('scope.pages should populated based on pages data.', function() {
        $httpBackend.flush();
        expect(pagesById).toEqualData(mock_page_results);
    });
    

    gives me

    ReferenceError: pagesById is not defined
    

    Do I have any other options besides attaching it to $scope?

  • akronymn
    akronymn over 11 years
    that makes sense but I get TypeError: Cannot read property 'pagesById' of undefined referring to the first line in my controller where I try to read this.pagesById
  • wless1
    wless1 over 11 years
    this is probably different in the scope where you're accessing it. In the first line of your controller, do var that = this;, and then access pagesById using that.pagesById
  • akronymn
    akronymn over 11 years
    heh - this is starting to look like a doctor seuss story. It worked though. I'm surprised that 'this' isn't in scope inside of a member function. Oh well Thank you. +1 vote and +1 green check!
  • wless1
    wless1 over 11 years
    heh. For more info on javascript scope: coding.smashingmagazine.com/2009/08/01/…
  • Robert
    Robert over 11 years
    I don't think that this is the appropriated way to test. You want to test the resulting scope, not the controller. Check stackoverflow.com/questions/14202767/… for more info.
  • wless1
    wless1 over 11 years
    There are times when your controller has data that you don't want to put on the scope...