我创建了一个我尝试使用Karma和Jasmine进行测试的组件。一切都适用于没有DI注入服务的其他组件。但是这个抛出一个没有任何消息的错误,只是堆栈。
这是组件:
import {Component} from 'angular2/core';
import {Application} from './application';
import {ApplicationsService} from './applications.service';
@Component({
selector: 'applications-selector',
styles: [require('./applications-selector.scss')],
template: require('./applications-selector.html'),
providers: [ApplicationsService]
})
export class ApplicationsSelectorComponent {
applications: Application[];
selectedWeek: number;
selectedApplications: Application[];
selectedCycle: string;
constructor(private _applicationsService: ApplicationsService) {
this.getApplications();
}
getApplications() {
this._applicationsService.getApplications().then(applications => this.applications = applications);
}
}
以下是此组件的单元测试:
import {
it,
inject,
injectAsync,
describe,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import {provide} from 'angular2/core';
import {ApplicationsSelectorComponent} from './applications-selector.component';
import {ApplicationsService} from './applications.service';
class ApplicationsServiceMock {
getApplications() {
return ['ABC', 'XYZ'];
}
}
describe('ApplicationsSelectorComponent', () => {
beforeEachProviders(() => [
provide(ApplicationsService, { useClass: ApplicationsServiceMock }),
ApplicationsSelectorComponent
]);
it('should have empty default values', inject([ApplicationsSelectorComponent], (component) => {
expect(component.selectedWeek).toBe(undefined);
expect(component.selectedApplications).toBe(undefined);
expect(component.selectedCycle).toBe(undefined);
}));
});
这是我在运行此测试时得到的错误:
ApplicationsSelectorComponent
× should have empty default values
PhantomJS 2.1.1 (Windows 7 0.0.0)
_instantiateProvider@d:/git/gatekeeper/web/spec-bundle.js:11896:38 <- webpack:///angular2/src/core/di/injector.ts:770:31
_new@d:/git/gatekeeper/web/spec-bundle.js:11885:42 <- webpack:///angular2/src/core/di/injector.ts:759:37
getObjByKeyId@d:/git/gatekeeper/web/spec-bundle.js:11495:55 <- webpack:///angular2/src/core/di/injector.ts:356:44
_getByKeyDefault@d:/git/gatekeeper/web/spec-bundle.js:12083:51 <- webpack:///angular2/src/core/di/injector.ts:977:44
_getByKey@d:/git/gatekeeper/web/spec-bundle.js:12029:42 <- webpack:///angular2/src/core/di/injector.ts:914:35
get@d:/git/gatekeeper/web/spec-bundle.js:11704:31 <- webpack:///angular2/src/core/di/injector.ts:577:26
d:/git/gatekeeper/web/spec-bundle.js:9128:74 <- webpack:///angular2/src/testing/test_injector.ts:151:52
map@[native code]
apply@[native code]
call@[native code]
call@[native code]
map@d:/git/gatekeeper/web/spec-bundle.js:2377:21 <- webpack:///~/es6-shim/es6-shim.js:1113:0
execute@d:/git/gatekeeper/web/spec-bundle.js:9128:39 <- webpack:///angular2/src/testing/test_injector.ts:151:34
execute@d:/git/gatekeeper/web/spec-bundle.js:9017:27 <- webpack:///angular2/src/testing/test_injector.ts:42:22
d:/git/gatekeeper/web/spec-bundle.js:8393:58 <- webpack:///angular2/src/testing/testing.ts:137:49
_instantiate@d:/git/gatekeeper/web/spec-bundle.js:12003:87 <- webpack:///angular2/src/core/di/injector.ts:883:67
在 inject([ApplicationsSelectorComponent] 语句中发生错误。一旦删除它,就没有错误,但是我需要这个组件来对它执行测试。
什么会导致这种注射错误?
答案 0 :(得分:2)
您似乎尝试以与无效的提供商相同的方式注入组件。
以下是特定组件的模拟提供程序的完整最小示例:
class ApplicationsService {
getApplications() {
return ['ABC'];
}
}
class ApplicationsServiceMock {
getApplications() {
return ['ABC', 'XYZ'];
}
}
@Component({
selector: 'apps',
template: '',
providers: [ApplicationsService]
})
class ApplicationsSelectorComponent {
constructor(private apps: ApplicationsService) {}
}
describe('App', () => {
describe('ApplicationsSelectorComponent', () => {
beforeEach(injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.overrideProviders(ApplicationsSelectorComponent, [provide(ApplicationsService, { useClass: ApplicationsServiceMock })])
.createAsync(ApplicationsSelectorComponent)
.then((componentFixture: any) => {
this.component = componentFixture;
});
}));
it('should have empty default values', () => {
expect(this.component.componentInstance.apps.getApplications()).toEqual(['ABC', 'XYZ'])
});
});
});
答案 1 :(得分:0)
最后,事实证明所有设置都是正确的,但我只是从ApplicationsServiceMock
返回了错误的值。基本服务正在返回Promise
,我在模拟中返回了一个值数组。这就是为什么当从this._applicationsService.getApplications().then(applications => this.applications = applications);
执行此行constructor
时,无法找到阵列上的然后方法。测试失败了。
一旦我从我的模拟中修复了返回值,一切正常
这是我测试的工作代码:
import {
it,
beforeEach,
injectAsync,
describe,
TestComponentBuilder
} from 'angular2/testing';
import {Component, provide} from 'angular2/core';
import {Application} from './application';
import {ApplicationsService} from './applications.service';
import {ApplicationsSelectorComponent} from './applications-selector.component';
class ApplicationsServiceMock {
getApplications() {
return Promise.resolve([{ 'id': 1, 'name': 'TST', 'project': 'PRJ' }]);
}
}
describe('ApplicationsSelectorComponent', () => {
beforeEach(injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.overrideProviders(ApplicationsSelectorComponent, [provide(ApplicationsService, { useClass: ApplicationsServiceMock })])
.createAsync(ApplicationsSelectorComponent)
.then((componentFixture: any) => {
this.component = componentFixture;
});
}));
it('should have empty default values', () => {
expect(this.component.componentInstance._applicationsService.getApplications().then(apps => { apps.toEqual([{ 'id': 1, 'name': 'TST', 'project': 'PRJ' }]) }));
});
});