1
votes

I am getting the error:

TypeError: Cannot read property '$scope' of undefined
at $controller (bower_components/angular/angular.js:10327:28)
at bower_components/angular-mocks/angular-mocks.js:2221:12
at Context. (src/client/app/peer-review/post-visit.controller.spec.js:11:18)

When running tests on an angularJS controller with mocha and karma.

The initialisation of the test it is trying to run is:

    describe('PostVisitController', function () {
      var controller;

      beforeEach(function () {
        bard.appModule('app.peer-review');
        bard.inject('$controller', '$log');
        controller = $controller('PostVisitController');
      });

      bard.verifyNoOutstandingHttpRequests();

      it('should be created successfully', function () {
        expect(controller).to.be.defined;
      });
    });

The controller it is testing doesn't require $scope, and tests on other controllers in the same module are passing fine.

1

1 Answers

2
votes

This is a misleading error.

When the controller is being instantiated angular runs the following code (from angular.js) which checks if the controller is in the list of defined controllers it has:

    return function $controller(expression, locals, later, ident) {
      var instance, match, constructor, identifier;
      later = later === true;
      if (ident && isString(ident)) {
        identifier = ident;
      }

      if (isString(expression)) {
        match = expression.match(CNTRL_REG);
        if (!match) {
          throw $controllerMinErr('ctrlfmt',
            "Badly formed controller string '{0}'. " +
            "Must match `__name__ as __id__` or `__name__`.", expression);
        }
        constructor = match[1],
        identifier = identifier || match[3];
        expression = controllers.hasOwnProperty(constructor)  <———————— HERE
            ? controllers[constructor]
            : getter(locals.$scope, constructor, true) ||
                (globals ? getter($window, constructor, true) : undefined);

        assertArgFn(expression, constructor, true);
      }

If it can’t find the controller in the array it runs a getter that try to read $scope from the ‘locals’ variable (which can be null).

The controller will not be in the array if it has not been included in the index file for your tests. Including the file will resolve the issue.