尝试使用一个简单的例子在angular-2中学习这个测试实用程序TestBed
并且击中了我的第一个阻止程序。 google或SO搜索没有产生任何匹配的示例,
所以,我有一个非常基本的组件header
,如下所示 -
import { Component } from '@angular/core';
@Component({
selector: 'header',
template: ''
})
export class HeaderComponent{
public title: string;
constructor(testparam: string){
this.title = 'test';
}
}
然后将其规格如下 -
import { TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
describe('HeaderComponent Test', () => {
let component: HeaderComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [HeaderComponent]
});
const fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
});
it('should have the component defined', () => {
expect(component).toBeDefined();
});
it('should initialize the title to test', () => {
expect(component.title).toBe('test');
});
});
运行业力测试就是投掷 -
Error: No provider for String! in karma.entry.js
karma.entry.js基本上只是为TestBed设置测试env配置,然后通过我的spec文件夹中的每个测试,下面是我的karma.entry.js
require('core-js/es6');
require('core-js/es7/reflect');
require('es6-shim');
require('reflect-metadata');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
require('rxjs/Rx');
const browserTesting = require('@angular/platform-browser-dynamic/testing');
const coreTesting = require('@angular/core/testing');
coreTesting.TestBed.initTestEnvironment(
browserTesting.BrowserDynamicTestingModule,
browserTesting.platformBrowserDynamicTesting()
);
const context = require.context('../src', true, /\.spec\.ts$/);
context.keys().forEach(context);
Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000;
如果我从组件类的构造函数中删除参数,测试会通过,所以我认为我缺少一些导致TestBed.createComponent(HeaderComponent)
无法正确编译组件的预配置。带有字符串类型参数的构造函数。
我可能遗失的任何线索?
更新
如果有帮助的话 - 根据@ mrkosima的回答,我更新的组件类现在看起来如下,单元测试现在通过好了:)
import { Component, OpaqueToken, Inject } from '@angular/core';
export let TITLE_TOKEN = new OpaqueToken('title token');
@Component({
selector: 'header',
template: '',
providers: [{ provide: TITLE_TOKEN, useValue: 'test' }]
})
export class HeaderComponent{
public title: string;
constructor(@Inject(TITLE_TOKEN) titleParam: string){
this.title = titleParam;
}
}
答案 0 :(得分:5)
你在构造函数的参数中找出问题的根本原因是正确的。
在组件实例化Injector
期间尝试解析构造函数中列出的所有依赖项。 Injector
按提供程序中的类型查找依赖项。
有关DI的更多信息,请访问:https://angular.io/docs/ts/latest/guide/dependency-injection.html
这意味着如果组件有constructor(authService: AuthService) { }
,则Injector
会在提供商中查找AuthService
令牌。
在您的情况下相同 - 您的组件取决于String
。
但是没有任何提供商使用String
令牌。
实际上,将原始类型列为依赖是错误的。
应使用
而不是OpaqueToken
export let TITLE_TOKEN = new OpaqueToken('title token');
在模块提供程序中配置令牌
providers: [{ provide: TITLE_TOKEN, useValue: 'title value' }]
比在组件中注入令牌:
constructor(@Inject(TITLE_TOKEN) title: string) {
this.title = title;
}
这是注入原语的正确用法。
此处有更多详情: https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#opaquetoken
PS:要测试组件,应将TITLE_TOKEN
添加到测试模块中:
import {TITLE_TOKEN} from ...
TestBed.configureTestingModule({
providers: [ { provide: TITLE_TOKEN, useValue: 'test' } ]
});
而不是创建测试组件,并期望title
为'test'
。