MatTaNg
MatTaNg

Reputation: 895

Mocking AngularJS services with Jasmine

I seem to be having trouble mocking out my service in my controller. Specifically 'momentsService'. Here is my test code.

describe('Moment Controller', function() {

    var $scope, $controller, momentsService, $ionicContentBanner, core, components, $q, $ionicPopup;

    beforeEach(module('app'));
    beforeEach(module('core'));
    beforeEach(module('components'));
    beforeEach(module('constants'));


    beforeEach(inject(function(_$controller_, _$rootScope_, _momentsService_, _$ionicContentBanner_, _core_, _components_, _$q_, _$ionicPopup_) {
        $scope = $rootScope.$new();
        momentsService = _momentsService_;
        $ionicContentBanner = _$ionicContentBanner_;
        core = _core_;
        components = _components_;
        $q = _$q_;
        $ionicPopup = _$ionicPopup_;

        spyOn(momentsService, 'initializeView');

        $controller = _$controller_('MomentsController', {
            momentsService: momentsService, 
            $scope: $scope, 
            $ionicContentBanner: $ionicContentBanner,
            core: core,
            component: components,
            $q: $q,
            $ionicPopup: $ionicPopup
        });
    }));

it('should initialize', function() {
    console.log("CONTROLLER");
    console.log(momentsService);
    console.log(momentsService.initializeView());
});

});

The last 3 console.log keeps giving me undefined for the 'momentsService'. In the terminal I'm getting 'undefined is not an object' So my service is not being mocked correctly and my test keeps failing.

Controller and dependencies:

(function() {
    angular.module('app.MomentsController', [])

    .controller('MomentsController', ['momentsService', '$scope', '$ionicContentBanner', 'core', 'components', '$q', '$ionicPopup', MomentsController]);

    function MomentsController (momentsService, $scope, $ionicContentBanner, core, components, $q, $ionicPopup) {
var vm = this;
//Omitted

What am I missing here?

Thanks for your help

-Matt

EDIT: I am using controllerAs syntax if that matters.

EDIT2: This still isn't working for me despite trying both of your fixes. momentsService is still undefined. My code stands as follows:

describe('Moment Controller', function() {

    var $scope, $controller, momentsService, $ionicContentBanner, core, components, $q, $ionicPopup;

    beforeEach(module('app'));
    beforeEach(module('core'));
    beforeEach(module('components'));
    beforeEach(module('constants'));


    beforeEach(inject(function(_$controller_, $rootScope, _momentsService_, _$ionicContentBanner_, _core_, _components_, _$q_, _$ionicPopup_) {
        var self = this;
        this.$scope = $rootScope.$new();
        this.momentsService = _momentsService_;

        this.$ionicContentBanner = _$ionicContentBanner_;
        this.core = _core_;
        this.components = _components_;
        this.$q = _$q_;
        this.$ionicPopup = _$ionicPopup_;

        spyOn(momentsService, 'initializeView');

        this.$controller = _$controller_('MomentsController', {
            momentsService: momentsService, 
            $scope: $scope, 
            $ionicContentBanner: $ionicContentBanner,
            core: core,
            component: components,
            $q: $q,
            $ionicPopup: $ionicPopup
        });
    }));

    it('should initialize', function() { 
        console.log(this);
        console.log("CONTROLLER");
        console.log(this.momentsService);
        console.log(this.momentsService.initializeView());
    });

});

I have tried without the this as well since the plunker posted in the comment didn't use it. If you disregard the this the code matches the plunker posted exactly, I just added other dependencies - Which when I comment out it still complains that my service is undefined. I don't get it.

Edit 3:

'files' in conf.js:

  files: [
      'lib/ionic/js/ionic.bundle.js',
      'lib/angular-mocks/angular-mocks.js',
      'js/*',
      'bestMoments/*',
      'moments/*',
      'submitMoment/*',
      'myMoments/*',
      'index.controller.js',
      'layout/mainView.directive.js',
    ],

Moments.Service.js dependencies:

(function() {
    angular.module('app.momentsService', [])

    .service('momentsService', ['core', '$q', 'constants', 'awsServices', 'components', 'logger', 'geolocation', momentsService]);

    function momentsService(core, $q, constants, awsServices, components, logger, geolocation){

File structure: enter image description here

Upvotes: 0

Views: 90

Answers (1)

bhantol
bhantol

Reputation: 9616

Assuming jasmine2 - notice all lines with self which is this. Any properties in beforeXXXX is available on this inside it and afterXXXX.

In your case the undefined is on console.log is for momentService which is undefined in it. That problem is solved by jasmine feature. Official jasmine - The this Keyword

describe('Moment Controller', function() {


    beforeEach(module('app'));
    beforeEach(module('core'));
    beforeEach(module('components'));
    beforeEach(module('constants'));


    beforeEach(inject(function(_$controller_, _$rootScope_, _momentsService_, _$ionicContentBanner_, _core_, _components_, _$q_, _$ionicPopup_) {
        var self = this;
        self.$scope = $rootScope.$new();
        var momentsService = self.momentsService = _momentsService_;
        self.$ionicContentBanner = _$ionicContentBanner_;
        self.core = _core_;
        self.components = _components_;
        self.$q = _$q_;
        self.$ionicPopup = _$ionicPopup_;

        spyOn(self.momentsService, 'initializeView');

        self.$controller = _$controller_('MomentsController', {
            momentsService: self.momentsService, 
            $scope: self.$scope, 
            $ionicContentBanner: self.$ionicContentBanner,
            core: self.core,
            component: self.components,
            $q: self.$q,
            $ionicPopup: self.$ionicPopup
        });
    }));

  it('should initialize', function() { 
      var self = this;
      console.log("CONTROLLER");
      console.log(self.momentsService);
      console.log(self.momentsService.initializeView());
  });

});

Upvotes: 1

Related Questions