2013-08-27 93 views
7

我使用茉莉花來測試我在TypeScript中編寫的控制器。我的單元測試使用純javascript。 當我測試我的控制器時,出現錯誤,我要注入一個模擬服務。在AngularJS/Jasmine中注入模擬服務

這是我測試的樣子:

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

我app.ts:

module game { 
    'use strict'; 

    var busybee = angular.module('busybee', []); 
    busybee.controller('configCtrl', ConfigCtrl); 

    busybee.service('configService', ConfigService); 
    ... 
    ... 

} 

和我的打字稿控制器:

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 
     } 
    } 
} 

當運行因果報應,我得到以下錯誤:

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) 

看來,注入configService時出現了問題,但我不知道爲什麼。

編輯:增加了的jsfiddle http://jsfiddle.net/Q552U/6/

UPDATE:這似乎是對具有在不同文件中的打字稿類的編譯的JavaScript茉莉問題。將TypeScript文件編譯爲一個.js文件(tsc --out dest.js source.ts),對我來說是這樣。

+1

您可以使用測試創建代碼的小提琴,以便每個人都可以查看它嗎? (因爲沒有多少人使用TypeScript,因此小提琴可能有助於調試。) – zsong

回答

12

嘗試使用$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}); 
})); 

鏈接到Demo

+0

非常感謝! – Johannes

+0

鏈接到演示將拋出一個404 – Braulio

4

zsong的答案很好,但是可以通過從angular.mock.inject()中刪除configService來進一步更新代碼,因爲這不是必需的。

另一種可能性是在TypeScript中編寫測試(並使用Jasmine類型定義),這是一種更簡潔的方法。在這種情況下,您的測試將如下所示:

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