Injecting Mock service in AngularJS/ Jasmine

28,034

Solution 1

Try get the service using $injector.

beforeEach(angular.mock.inject(function($rootScope, $http, $location, $timeout, configService, $controller, $injector){
    scope = $rootScope.$new();
    http = $http;
    location = $location;
    timeout = $timeout;
    service = $injector.get('configService'); //not sure the name, you may try 'ConfigService' as well.

    $controller('configCtrl', {$scope: scope, $http: http, $location: location, $timeout: timeout, configService: service});
}));

Link to Demo.

Solution 2

Nice answer from zsong, but that code can be updated further by removing configService from angular.mock.inject() as it is not necessary.

Another possibility is to write your test in TypeScript (and use Jasmine type definitions), which is a cleaner way to do it. In that case, your test will look like this:

/// <reference path="typings/jasmine/jasmine.d.ts" />

describe('ConfigCtrl', () => {
    var configCtrl, scope, http, location, timeout, configServiceFake;

    beforeEach(angular.mock.module('busybee'));

    beforeEach(angular.mock.inject(($rootScope, $http, $location, $timeout, configService) => {
        scope = $rootScope.$new();
        http = $http;
        location = $location;
        timeout = $timeout;
        configServiceFake = configService;

        configCtrl = new game.ConfigCtrl(scope, http, location, timeout, configServiceFake);
    }));

    it('should have text = "constructor"', () => {
        expect(true).toBe(true);
    });
});
Share:
28,034
pichsenmeister
Author by

pichsenmeister

Updated on July 09, 2022

Comments

  • pichsenmeister
    pichsenmeister almost 2 years

    I'm using jasmine to test my controllers, which I wrote in TypeScript. My unit tests are in plain javascript. I'm getting an error when I test my controller, where I want to inject a mock service.

    This is how my test looks:

    'use strict';
    
    describe('ConfigCtrl', function(){
        var scope, http, location, timeout, $httpBackend, service;
    
        beforeEach(angular.mock.module('busybee'));
    
        beforeEach(angular.mock.inject(function($rootScope, $http, $location, $timeout, configService, $controller){
    
            scope = $rootScope.$new();
            http = $http;
            location = $location;
            timeout = $timeout;
            service = configService;
    
    
            $controller('configCtrl', {$scope: scope, $http: http, $location: location, $timeout: timeout, configService: service});
        }));
    
        it('should have text = "constructor"', function(){
            expect(true).toBe(true);
        });
    }); 
    

    My app.ts:

    module game {
        'use strict';
    
        var busybee = angular.module('busybee', []);
        busybee.controller('configCtrl', ConfigCtrl);
    
        busybee.service('configService', ConfigService);
        ...
        ...
    
    }
    

    and my TypeScript controller:

    module game {
        'use strict';
    
        export class ConfigCtrl {
    
            static $inject: string[] = ['$scope', '$http', '$location', '$timeout', 'configService'];
    
            constructor($scope: ng.IScope, $http: ng.IHttpService, $location: ng.ILocationService,
                $timeout: ng.ITimeoutService, configService: game.ConfigService) {  
                //any code here
            }
        }   
    }
    

    When running karma, I get the following error:

    Chrome 28.0.1500 (Linux) ConfigCtrl should have text = "constructor" FAILED
            TypeError: Cannot read property 'prototype' of undefined
                at Object.instantiate (/home/david/git/busybee2-client/js/libs/angular/angular.min.js:28:283)
                at Object.<anonymous> (/home/david/git/busybee2-client/js/libs/angular/angular.min.js:28:494)
                at Object.d [as invoke] (/home/david/git/busybee2-client/js/libs/angular/angular.min.js:28:174)
                at /home/david/git/busybee2-client/js/libs/angular/angular.min.js:29:339
                at c (/home/david/git/busybee2-client/js/libs/angular/angular.min.js:27:13)
                at Object.d [as invoke] (/home/david/git/busybee2-client/js/libs/angular/angular.min.js:27:147)
                at workFn (/home/david/git/busybee2-client/js/libs/angular/angular-mocks.js:1778:20)
            Error: Declaration Location
                at Object.window.jasmine.window.inject.angular.mock.inject [as inject] (/home/david/git/busybee2-client/js/libs/angular/angular-mocks.js:1764:25)
                at null.<anonymous> (/home/david/git/busybee2-client/js/test/ConfigCtrlSpecs.js:9:29)
                at /home/david/git/busybee2-client/js/test/ConfigCtrlSpecs.js:3:1
    Chrome 28.0.1500 (Linux): Executed 1 of 1 (1 FAILED) ERROR (0.329 secs / 0.032 secs)
    

    It seems, there's a problem injecting the configService, but I don't have an idea why.

    EDIT: added a jsfiddle http://jsfiddle.net/Q552U/6/

    UPDATE: It seems it was a problem for jasmine having the compiled javascript of the TypeScript classes in different files. Compiling the TypeScript files to a single .js file (tsc --out dest.js source.ts), does it for me.

  • Braulio
    Braulio about 7 years
    Link to Demo throws a 404