Karma tests does not seem to load my Angularjs controller

11,534

Solution 1

I solved my problem, I've spent nearly a week to figure why this was not working.

I'd like to warn you, that Karma Stacktrace and error reports, even in debug mode, were not showing clues and were mainly missleading. I've spent time in javascript debugger jumping frame to frame, to understand why my controllers where not loaded. ( Inspecting Angular's controllers register, shown it was empty)

While digging in my directories I've found a *.js that were not loaded in the index in production but by the globbing pattern in tests.

It was my old http_interceptor service that I moved but did not trashed the file. Removing this buggy file fixed the weird Karma/Jasmine/Angular behaviour.

Lesson learned : Do not trust tests output ( but what should I trust then ? ). Remove files you are not using/testing.

Thanks to everyone who tryied to solve this issue.

Solution 2

i think the main problem is coming from the karma conf :

files: [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular-mocks/angular-mocks.js',
      'app/bower_components/angular-resource/angular-resource.js',
      'app/bower_components/angular-cookies/angular-cookies.js',
      'app/bower_components/angular-sanitize/angular-sanitize.js',
      'app/scripts/*.js',
      'app/scripts/**/*.js',
      'app/scripts/**/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],  

removing the * and specifying files one by one in the correct order, because if one is loaded before another it can break.

Edit : Add your files in the same order as your index.html

Solution 3

looking at this I'm wondering if the error message is confusing things.

in the stack trace i can see

TypeError: 'undefined' is not an object (evaluating 'scope.awesomeThings.length')

and from the example it does seem as though you have not defined any properties on the scope in your controller.

do you still have the problem if you add

$scope.awesomeThings = []; 

to your controller?

Solution 4

If you're using the latest angular and also using the angular-route module, you should include the angular-route script in the karma conf file too:

files: [
  'app/bower_components/angular/angular.js',
  'app/bower_components/angular-route/angular-route.js',
  'app/bower_components/angular-mocks/angular-mocks.js',
  'app/bower_components/angular-resource/angular-resource.js',
  'app/bower_components/angular-cookies/angular-cookies.js',
  'app/bower_components/angular-sanitize/angular-sanitize.js',
  'app/scripts/*.js',
  'app/scripts/**/*.js',
  'app/scripts/**/**/*.js',
  'test/mock/**/*.js',
  'test/spec/**/*.js'
],  

I had this problem and adding it to the karma file did the trick.

Share:
11,534
Meta Lambda
Author by

Meta Lambda

Updated on June 14, 2022

Comments

  • Meta Lambda
    Meta Lambda almost 2 years

    I run my angular tests with karma, my application is running fine in browser, but tests fails and I am suspecting wrong settings.

    Here are the controllers and tests :

    // app/scripts/controllers/main.js
    
    'use strict';
    
    angular.module('GloubiBoulgaClientApp')
      .controller('MainCtrl', function ($scope) {
    
      }); 
    

    Here is the test file :

    'use strict';
    
    describe('Controller: MainCtrl', function () {
    
      // load the controller's module
      beforeEach(module('GloubiBoulgaClientApp'));
    
      var MainCtrl,
        scope;  
    
      // Initialize the controller and a mock scope
      beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        MainCtrl = $controller('MainCtrl', {
          $scope: scope
        });
      }));  
    
      it('should attach a list of awesomeThings to the scope', function () {
        expect(true).toBe(true);
      });
    });
    

    The karma conf

    module.exports = function(config) {
      config.set({
        // base path, that will be used to resolve files and exclude
        basePath: '', 
    
        // testing framework to use (jasmine/mocha/qunit/...)
        frameworks: ['jasmine'],
    
        // list of files / patterns to load in the browser
        files: [
          'app/bower_components/angular/angular.js',
          'app/bower_components/angular-mocks/angular-mocks.js',
          'app/bower_components/angular-resource/angular-resource.js',
          'app/bower_components/angular-cookies/angular-cookies.js',
          'app/bower_components/angular-sanitize/angular-sanitize.js',
          'app/scripts/*.js',
          'app/scripts/**/*.js',
          'test/mock/**/*.js',
          'test/spec/**/*.js'
        ],  
    
        // list of files / patterns to exclude
        exclude: [], 
    
        // web server port
        port: 8080,
    
        // level of logging
        // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
        logLevel: config.LOG_INFO,
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,
    
    
        // Start these browsers, currently available:
        // - Chrome
        // - ChromeCanary
        // - Firefox
        // - Opera
        // - Safari (only Mac)
        // - PhantomJS
        // - IE (only Windows)
        browsers: ['PhantomJS'],
    
    
        // Continuous Integration mode
        // if true, it capture browsers, run tests and exit
        singleRun: false
      });
    };
    

    The error ouput

     PhantomJS 1.9.2 (Linux) Controller: MainCtrl should attach a list of awesomeThings to the scope FAILED
             Error: [ng:areq] Argument 'MainCtrl' is not a function, got undefined
             http://errors.angularjs.org/1.2.8-build.2094+sha.b6c42d5/ng/areq?p0=MainCtrl&p1=not%20a%20function%2C%20got% 2
     0undefined
                 at assertArg (--obfuscated-path--GloubiBoulga/GloubiBoulgaClient/app/bower_components/angular/angula
     r.js:1362)
                 at assertArgFn (--obfuscated-path--GloubiBoulga/GloubiBoulgaClient/app/bower_components/angular/angu
     lar.js:1373)
                 at --obfuscated-path--GloubiBoulga/GloubiBoulgaClient/app/bower_components/angular/angular.js:6763
                 at --obfuscated-path--GloubiBoulga/GloubiBoulgaClient/test/spec/controllers/main.js:15
                 at invoke (--obfuscated-path--GloubiBoulga/GloubiBoulgaClient/app/bower_components/angular/angular.j
     s:3704)
                 at workFn (--obfuscated-path--GloubiBoulga/GloubiBoulgaClient/app/bower_components/angular-mocks/angular -mocks.js:2120)
    

    I am wondering why this happen, I tried to find some documentation about the karma initialization with angularjs. But the most documentation I found is only dummy tutorial that are repeating the same pattern ( like the dummy todo list, but with phones ... )

    It seem that $controllerProvide.register fails to resolve my controllers name. But Directives tests are working correctly ...

    Thanks for your attention.

    Edit Notes : I replaced the controller PersonCtrl by MainCtrl in this thread because It was confusing people about where to look. Now MainCtrl is the simpliest failing example I found.

    This issue is only affecting my controllers, ( all of them ), but tests for Services and Directives are working as expected