Kaidjin
Kaidjin

Reputation: 1513

Jasmine spies on Angular services

I am trying to set up tests on an angular controller using jasmine and karma. I can't put all of my code here because it is quite big, but here are some samples of my code:

CompilerController.js (that's the controller I want to test)

(function() {
    angular.module('webcompiler')
        .controller('CompilerController', ['templateService', 'compilationService', CompilerController] );

    function CompilerController(templateService, compilationService) {
        var vm = this;

        /// Initialization
        (function() {
            vm.template = 'c_basic.c';
            ...
        })();

        /// Public members
        vm.loadTemplate = loadTemplate;

        /// Implementation
        function loadTemplate() {
            templateService.get(vm.template, function(source) {
                vm.sourcecode = source;
            });
        }
    }
})();

CompilerController.spec.js

  describe('CompilerController', function() {
    var CompilationService, TemplateService, controller;

    beforeEach(function() {
      module('webcompiler');
    });

    beforeEach(function() {
      inject(function(_$controller_, _TemplateService_, _CompilationService_) {
        CompilationService = _CompilationService_;
        TemplateService = _TemplateService_;
        spyOn(TemplateService, 'get').and.callFake(function(code, callback) {
          callback('c_basic_content');
        });
        controller = _$controller_('CompilerController');
      });
    });

    it('starts with default template as source', function() {
      expect(controller.template).toBe('c_basic.c');
      expect(controller.sourcecode).toBe('c_basic_content');
    });

    describe('loadTemplate function', function() {
      it('changes the content of the source area when called', function() {

        spyOn(TemplateService, 'get').and.callFake(function(code, callback) { // Does this work ? Changing the spy after injection ?
          if(code == 'c_parameters.c') { callback('c_parameters_content'); }
        });
        controller.template = 'c_parameters.c';
        controller.loadTemplate();
        expect(controller.sourcecode).toBe('c_parameters_content');
      });
    });
  });

Despite the fact that I'm not even sure that this works (changing a spy after the controller was created, see my commented line), all of the tests in this file fail with the following error :

PhantomJS 1.9.8 (Windows 7 0.0.0) CompilerController loadTemplate function changes the content of the source area when called FAILED Error: [$injector:unpr] Unknown provider: TemplateServiceProvider <- TemplateService

Here is a piece of my karma.conf.js :

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: [
            // bower:js
            'main/webapp/bower_components/jquery/dist/jquery.js',
            'main/webapp/bower_components/angular/angular.js',
            'main/webapp/bower_components/angular-cache-buster/angular-cache-buster.js',
            'main/webapp/bower_components/bootstrap/dist/js/bootstrap.js',
            'main/webapp/bower_components/angular-mocks/angular-mocks.js',
            // endbower
            'main/webapp/js/webcompiler.module.js',
            'main/webapp/js/TemplateService.js',
            'main/webapp/js/CompilationService.js',
            'main/webapp/js/CompilerController.js',
            'test/javascript/**/*.coffee' // I use coffeescript for the specs. The file I showed in this question are the compiled version.
        ],
        // Browser on which to test
        browsers: ['PhantomJS'],
        // Compile coffeescript specs
        preprocessors: {
          'test/javascript/**/*.coffee': ['coffee']
        },
        coffeePreprocessor: {
          options: {
            bare: true,
            sourceMap: false
          },
          transformPath: function(path) {
            return path.replace(/\.coffee/, '.js')
          }
        }
    });
};

Upvotes: 1

Views: 391

Answers (1)

olysachok
olysachok

Reputation: 309

Inside the controller you are injecting the service "templateService" using lowercase but it is injected in uppercase inside beforeEach function. May be it will help.

Upvotes: 2

Related Questions