Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: Unit testing controller returns "TypeError: $scope.$watch is not a function"

I want to write a simple test for a controller that

  • sets a variable of the scope to an ID
  • calls a function that triggers an API call with the ID on the scope
  • log the result
    describe('The app', () => {

      beforeEach(angular.mock.module('myModule'));

      var $controller;
      var eId = 123456;

      beforeEach(angular.mock.inject((_$controller_) => {
          $controller = _$controller_;
      }));


      describe('directive', () => {
          it('should load the data from the api', () => {
              var scope = {};
              var controller = $controller('myController', { $scope: scope });
              scope.entityId = eId;
              expect(scope.entityId).toBe(eId);

              controller.load(); // API call using scope.entityId, to load some data into the scope
              scope.$digest();
              console.log("entities:", controller.entities); // Where the data should be loaded into
          });
      });
    });

My controller uses the "controller as" syntax.

My test is run with karma and it gives me back the following error:

TypeError: $scope.$watch is not a function | at myController.watchChanges

Any hint in the right direction greatly appreciated!

like image 699
Timo Avatar asked Dec 19 '22 17:12

Timo


1 Answers

You have created a scope like an empty object, it is not really correct. You should create it like an new instance of $rootScope. Check out the code example:

 describe('The app', () => {

    beforeEach(angular.mock.module('myModule'));

    var $controller, $rootScope;
    var eId = 123456;

    beforeEach(angular.mock.inject((_$controller_, _$rootScope_) => {
        $controller = _$controller_;
        $rootScope = _$rootScope_;
    }));


    describe('directive', () => {
        it('should load the data from the api', () => {
            var scope = $rootScope.$new();
            var controller = $controller('myController', { $scope: scope });
            scope.entityId = eId;
            expect(scope.entityId).toBe(eId);

            controller.load(); // API call using scope.entityId, to load some data into the scope
            scope.$digest();
            console.log("entities:", controller.entities); // Where the data should be loaded into
        });
    });
});

Hope it will help you!

like image 60
Mikki Kobvel Avatar answered Jan 13 '23 10:01

Mikki Kobvel