简体   繁体   中英

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')
          }
        }
    });
};

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM