Testing modular AngularJS w/ Jasmine & Karma

16,168

Solution 1

Often a Unknown Provider error comes from files not being loaded, or being loaded in the incorrect order. Check which files are present while your tests are running.

Solution 2

Such kind of errors mostly occur due to incorrect declaration of files inside karma.config.js file. For setup of karma-jasmine all the files inside file:[] block of karma.config.js file should be in sequence in which they are expected to get loaded. Main module is having dependency injection of any custom service then load that service first and then main module.

Share:
16,168

Related videos on Youtube

Scott Silvi
Author by

Scott Silvi

Full stack software engineer with experience on both LAMP & .NET stacks. Stack of choice is back-end agnostic JSON web service, consumed by front-end JS framework. Previously would have said Backbone, but after working with AngularJS, I have to say it's the bees knees. I'm also becoming a bit of a workflow automation geek. Me and grunt? Let's just say my wife has cause to be jealous. I'm an entreprenerd - I work almost excluslively with early stage companies.

Updated on July 12, 2022

Comments

  • Scott Silvi
    Scott Silvi almost 2 years

    Struggling to get unit testing set up in Jasmine/Karma. I have a controller with a service dependency, and that service has another service dependency. I am not organizing my modules by type (Directives, Services, etc), but rather by feature (layout, summaryView, etc).

    Here's the architecture:

    angular.module('myApp', ['ngResource', 'myApp.base', 'myApp.layout','myApp.common']);
    angular.module('myApp.base', ['myApp.common']);
    angular.module('myApp.common',[]);
    angular.module('myApp.layout',['myApp.common']);
    

    Controller:

    angular.module('myApp.layout')
        .controller('LayoutCtrl', ['$scope', '$rootScope', '$timeout', 'layoutService', 'urlService', 'BaseService',
            function ($scope, $rootScope, $timeout, layoutService, urlService, BaseService) {
                //controller code here
        });
    

    Layout Service:

     angular.module('myApp.layout')
        .service('layoutService', ['$http', '$resource', '$rootScope', '$location', '$route', 'errorHandlingService', 'utilService',
            function ($http, $resource, $rootScope, $location, $route, errorHandlingService, utilService) {
                //service code here
        });
    

    From what I understand, if I simply include beforeEach(module('myApp.layout'));, I should have access to my controllers, services, filters, and directives in my layout module.

    Instead, the following code fails:

    describe('Layout Controller', function() {
      var ctrl, scope, service;
    
      beforeEach(module('myApp'));
      beforeEach(module('myApp.layout'));
      beforeEach(inject(function($controller, $rootScope, layoutService) {
    
          scope = $rootScope.$new();
          service = layoutService;
          //Create the controller with the new scope
          ctrl = $controller('LayoutCtrl', {$scope: scope, layoutService: service});
          dump(scope);
        }));
        it('should exist', function() {
            expect(ctrl).toBeDefined();
        });
    });
    

    With this error:

    Chrome 26.0 (Mac) Layout Controller should exist FAILED
        Error: Unknown provider: layoutServiceProvider <- layoutService
            at Error (<anonymous>)
            at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js:28:236
            at Object.c [as get] (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js:26:13)
            at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js:28:317
            at c (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js:26:13)
            at Object.d [as invoke] (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js:26:147)
            at workFn (http://code.angularjs.org/1.0.4/angular-mocks.js:1754:20)
        Error: Declaration Location
            at window.jasmine.window.inject.angular.mock.inject (http://code.angularjs.org/1.0.4/angular-mocks.js:1740:25)
            at null.<anonymous> (/Users/scottsilvi/svn/BARO/web/src/test/js/unit/myApp.layoutModule.js:6:14)
            at /Users/scottsilvi/svn/BARO/web/src/test/js/unit/myApp.layoutModule.js:1:1
        Expected undefined to be defined.
        Error: Expected undefined to be defined.
            at null.<anonymous> (/Users/scottsilvi/svn/BARO/web/src/test/js/unit/myApp.layoutModule.js:15:16)
    Chrome 26.0 (Mac): Executed 10 of 10 (1 FAILED) (0.36 secs / 0.014 secs)
    

    Thoughts?

    • Jmr
      Jmr almost 11 years
      Are you sure that all files are being loaded and are being loaded in the correct order?
  • George Stocker
    George Stocker almost 9 years
    @Jmr how do you detect which files are present when tests are running?
  • Jay
    Jay about 8 years
    @GeorgeStocker Run karma with logLevel DEBUG