2013-08-27 80 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); 
    }); 
});