在 AngularJS/Jasmine 中注入 Mock 服务
Posted
技术标签:
【中文标题】在 AngularJS/Jasmine 中注入 Mock 服务【英文标题】:Injecting Mock service in AngularJS/ Jasmine 【发布时间】:2013-08-30 10:26:29 【问题描述】:我正在使用 jasmine 来测试我用 TypeScript 编写的控制器。我的单元测试是用纯 javascript 编写的。 我在测试控制器时遇到错误,我想在其中注入模拟服务。
这是我的测试的样子:
'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);
...
...
还有我的 TypeScript 控制器:
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
运行 karma 时,出现以下错误:
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/
更新:对于 jasmine 来说,将 TypeScript 类的编译后的 javascript 放在不同的文件中似乎是个问题。将 TypeScript 文件编译为单个 .js 文件 (tsc --out dest.js source.ts
),对我有用。
【问题讨论】:
你能创建一个带有测试的代码,让每个人都可以看一下吗? (因为使用 TypeScript 的人不多,所以 fiddle 可能有助于调试。) 【参考方案1】:尝试使用$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。
【讨论】:
链接到演示会抛出 404【参考方案2】: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);
);
);
【讨论】:
以上是关于在 AngularJS/Jasmine 中注入 Mock 服务的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS Jasmine 测试失败:无法实例化模块