Search code examples
angularjsunit-testingjasminekarma-jasminespyon

Jasmine Js - SpyOn Fakecall during the controller initialization


I have seen a set of duplicates for this question but was unable to solve the issue.

I have a controller and during the controller initialization, fetchtemplate() is getting called first and then my mock fetchtemplate() is getting called.

How do I stop the actual(controller) fetchtemplate() getting called during the controller initialization? My intention is to mock the function fetchtemplate() in my spec.Please have a look at my spec -

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

   this.init = function() {
                  $controller('ChangeControlCreateController', {
                    $scope: scope
                  });
                }
    }));
    describe('Function', function() {

        it("-- check for trueness",function(){

        this.init()     ; //Initialization of the controller
        spyOn(scope,'fetchtemplate').and.callFake(function() {
                  return 101;
                });
        var fakeResponse = scope.fetchtemplate();
        expect(scope.fetchtemplate).toHaveBeenCalled();
        expect(fakeResponse).toEqual(101);      
        });


    });
});

I have tried placing the spyOn before the this.init() which gave error as the fetchtemplate() doesn't exist at that time to spyOn.

My controller code structure looks like -

angular.module('...', [...])

  .controller('ChangeControlCreateController', ["$scope"...,
    function ChangeControlCreateController($scope,...) {
        $scope.fetchtemplate = function() {
            console.log("controller's function");            
            ...
        };
        $scope.fetchtemplate();
    });

The result what I am getting is - First the console item "controller's function" and then the spec is executing with mock function. I want the mock function to execute without the controller's function to execute


Solution

  • So if I understand correctly you are doing some call to a function that is doing something you want to prevent for test purposes. Probably an http call or some thing of the sort ?

    Whatever it is doing the proper way to handle something like that is usually to put that method inside a service instead and then to spy on that service method. Here is an example of test if the service is TemplateService :

    describe("...",function(){
    
    var $controller, scope, TemplateService, YourController;
    
    beforeEach(inject(function(_$controller_, _TemplateService_, ...) {
      scope = $rootScope.$new();
      $controller = _$controller_;
      TemplateService = _TemplateService_;  
    }
    
    it("-- check for trueness",function(){
    
      spyOn(TemplateService,'fetchTemplate').and.returnValue('101');
    
    YourController = $controller('YourController'); 
      expect(...);
    });
    
    
    });
    

    I hope that's helpful