Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Testing: Spy a function that was executed on the initialize of a controller

I've been trying to spy a function that was executed on the initialize of a controller, but the test always failed. I've been trying execute $scope.$digest() and this it's not working, However in the console, i see that the function have been called.

I can't figure out this, Someone can explain to me why this it's not working?

Codepen Example: http://codepen.io/gpincheiraa/pen/KzZNby

Controller

function Controller($stateParams, $scope){

  $scope.requestAuthorization = requestAuthorization;

  if ($stateParams.requestAuthorization === true) {
    console.log('$stateParams.requestAuthorization');
    $scope.requestAuthorization();
  }
  function requestAuthorization() {
    console.log('requestAuthorization()');
  }
}

Testing

describe('AppCtrl', function(){
     var AppCtrl, $rootScope, $scope, $stateParams;

    beforeEach(module('exampleApp'));

    beforeEach(inject(function($controller, _$rootScope_, _$injector_, _$stateParams_) {
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $stateParams = _$stateParams_;
        $stateParams.requestAuthorization = true;


        AppCtrl = $controller('AppCtrl',{
            $scope: $scope,
            $stateParams : $stateParams
        });

        spyOn($scope, 'requestAuthorization');          
    }));

     it('$stateParams.requestAuthorization should be defined', function() {             
        expect($stateParams.requestAuthorization).toBeDefined();
    });

    it('$scope.requestAuthorization should be defined', function() {
        expect($scope.requestAuthorization).toBeDefined();
    });

    // this test is not passing.. 
    it('should call requestAuthorization', function() {
                //$scope.$digest();
        expect($scope.requestAuthorization).toHaveBeenCalled();
    });

});
like image 307
Gonzalo Pincheira Arancibia Avatar asked Apr 08 '16 15:04

Gonzalo Pincheira Arancibia


People also ask

Why would you use a spy in a test in angular?

A Spy is a feature of Jasmine which lets you take an existing class, function, or object and mock it in such a way that you can control what gets returned from function calls. We create a real instance of AuthService and inject it into the LoginComponent .

Why use spy Jasmine?

A Jasmine spy can stub any function and track all calls to that function and all of its arguments. Jasmine Spies are a powerful tool to use in unit testing because they allow us to focus on the function that is being tested.


1 Answers

Your test is failing because spy gets overridden by real function when controller initializes. One way to avoid this is monkey-patching $scope object with custom setter for requestAuthorization property, that could create spy when controller is trying to assign value to this property:

    beforeEach(inject(function($controller, _$rootScope_, _$injector_, _$stateParams_) {
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        var reqAuthSpy;
        Object.defineProperty($scope, 'requestAuthorization', {
            get: function() {return reqAuthSpy;},
            set: function(fn) {
             reqAuthSpy = jasmine.createSpy('reqAuthSpy');
            }
        });
        $stateParams = _$stateParams_;
        $stateParams.requestAuthorization = true;


        AppCtrl = $controller('AppCtrl',{
            $scope: $scope,
            $stateParams : $stateParams
        });

    }));
like image 120
Stubb0rn Avatar answered Oct 20 '22 01:10

Stubb0rn