首先我搜索了“没有Http提供程序”,因为错误显示,但我意识到我已经在videoplayer.component中导入了http,但我并没有使用它。但我学到了很多关于模拟服务的知识,特别是the post on an observable abstract mock up非常有帮助。从videoplayer.component中删除http后,我遇到了下一个错误:未定义VideoService。我忘记了测试模块中的导入!在测试组件中解析后,我再次收到“No Provider for HTTP”。
首先我的测试代码( videoplayer.component.spec.ts )与上面的帖子中的模拟
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { async } from '@angular/core/testing';
import { AbstractMockObservableService }
from '../shared/test/abstract.mock.observable.service';
import { VideoPlayer } from './videoplayer.component';
import { VideoService } from './video.service';
describe('VideoPlayer (inline template)', () => {
class MockService extends AbstractMockObservableService {
getLoading(cb) {
return true;// stubbing?
}
pushLoadState() {
return false;// stubbing?
}
getOptions(requestDisplayId) : Observable<VideoDetail> {
return false;// return Observable???
}
reservePlayer(displayID,domID) { // TODO register ids?
return false;
}
}
let mockService;
let comp: VideoPlayer;
let fixture: ComponentFixture<VideoPlayer>;
let de: DebugElement;
let el: HTMLElement;
// async beforeEach
beforeEach(async(() => {
mockService = new MockService();
TestBed.configureTestingModule({
declarations: [ VideoPlayer ], // declare the test component
providers: [ {provide: VideoService, useValue: mockService } ],
})
.compileComponents(); // compile template and css
}));
// synchronous befareEach...
beforeEach(() => {
fixture = TestBed.createComponent(VideoPlayer);
comp = fixture.componentInstance; // VideoPlayer test instance
// query for the title <h1> by CSS element selector
de = fixture.debugElement.query(By.css('.videocontainer'));
el = de.nativeElement;
console.log(de);
console.log(el);
});
it('SOME CONTENT', () => {
});
});
现在 videoplayer.component.ts ,请原谅Youtube iFrame-API的直接dom操作,我仍然在寻找与Angular2兼容的方式。
import {Component,Input,Output,Inject,ElementRef} from '@angular/core';
import {NgIf} from '@angular/common';
import {VideoService} from './video.service';
@Component({
selector: 'my-video-player',
providers: [VideoService],
template: require('./videoplayer.html'),
})
export class VideoPlayer implements OnChanges {
@Input() displayid : String;
@Input() displayflag : Number;
// -1 button to load player,0 no display,1 load but dont start,
// 2 autostart after load
@Output() onStateChange = new EventEmitter<any>();
private options : Object;
private loadingFlag : boolean;
private errorFlag : boolean;
private myPlayer : Object;
ngOnChanges(changes: SimpleChanges) {
var refreshed = false;
if (changes.includes('displayid'))
{
let did = changes['displayid'];
if (did.previousValue !== did.currentValue) {
refreshPlayer();
refreshed = true;
}
}
if (!refreshed && changes.includes('displayid'))
{
let did = changes['displayflag'];
if (did.previousValue !== did.currentValue) {
refreshPlayer();
refreshed = true;
}
}
/*for (let propName in changes) {
let chng = changes[propName];
let cur = JSON.stringify(chng.currentValue);
let prev = JSON.stringify(chng.previousValue);
}*/
}
constructor(@Inject(ElementRef) elr: ElementRef,
@Inject(VideoService) videoService: VideoService) {
this.loadingFlag = true;
}
ngOnInit() {
refreshPlayer();
}
loadPlayer() {
this.displayflag = 2;
this.refreshPlayer();
}
refreshPlayer() {
// loadingFlag with Callback
this.loadingFlag = videoService.getLoading(this.refreshPlayer);
if (this.loadingFlag) return;
if (this.myPlayer !== null) {
this.myPlayer.destroy();
this.myPlayer = null;
}
this.errorFlag = false;
if (this.displayid !== null && this.displayflag > 0) {
console.log('refreshPlayer: ' + this.displayid);
videoService.getOptions(this.displayid)
.subscribe(
this.getOptionsOnNext,
this.getOptionsOnError,
this.getOptionsOnCompleted
);
}
}
private getOptionsOnNext(data) {
this.displayid = data.displayid; //?
var myId = 'vp'+this.displayid;
// check if element exists
if (document.getElementById(myId)===null)
{
var newNode = document.createElement("div");
newNode.id = myId;
elr.nativeElement.insertBefore(newNode);
}
this.options = data.options;
this.options.events = {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onError': onPlayerError,
};
this.myPlayer = new YT.Player(myId, options);
videoService.reservePlayer(this.displayid,myId);
}
private getOptionsOnError(err) {
// console.log(err);
this.errorFlag = true;
}
private getOptionsOnCompleted() {
console.log('getOptionsOnCompleted: ' + this.displayid);
}
private onPlayerReady(event) {
if (this.displayflag == 2)
event.target.playVideo();
}
private onPlayerStateChange(event) {
onStateChange.emit(event.data);
}
private onPlayerError(event) {
console.log(event);
errorFlag = true;
}
}
这是堆栈跟踪,什么也没告诉我。
Error: No provider for Http!
Error: DI Error
at NoProviderError.ZoneAwareError (webpack:///~/zone.js/dist/zone.js:811:0 <- src/polyfills.ts:3833:33)
at NoProviderError.BaseError [as constructor] (webpack:///~/@angular/core/src/facade/errors.js:22:0 <- src/test.ts:22301:16)
at NoProviderError.AbstractProviderError [as constructor] (webpack:///~/@angular/core/src/di/reflective_errors.js:54:0 <- src/test.ts:45305:16)
at new NoProviderError (webpack:///~/@angular/core/src/di/reflective_errors.js:116:0 <- src/test.ts:45367:16)
at ReflectiveInjector_._throwOrNull (webpack:///~/@angular/core/src/di/reflective_injector.js:485:0 <- src/test.ts:63446:19)
at ReflectiveInjector_._getByKeyDefault (webpack:///~/@angular/core/src/di/reflective_injector.js:524:0 <- src/test.ts:63485:25)
at ReflectiveInjector_._getByKey (webpack:///~/@angular/core/src/di/reflective_injector.js:456:0 <- src/test.ts:63417:25)
at ReflectiveInjector_.get (webpack:///~/@angular/core/src/di/reflective_injector.js:325:0 <- src/test.ts:63286:21)
at TestBed.get (webpack:///~/@angular/core/bundles/core-testing.umd.js:827:0 <- src/test.ts:8978:67)
at CompiledTemplate.proxyViewClass.AppView.injectorGet (webpack:///~/@angular/core/src/linker/view.js:152:0 <- src/test.ts:64221:45)
at CompiledTemplate.proxyViewClass.DebugAppView.injectorGet (webpack:///~/@angular/core/src/linker/view.js:580:0 <- src/test.ts:64649:49)
at CompiledTemplate.proxyViewClass.View_VideoPlayer_Host0.createInternal (/DynamicTestModule/VideoPlayer/host.ngfactory.js:19:55)
at CompiledTemplate.proxyViewClass.AppView.createHostView (webpack:///~/@angular/core/src/linker/view.js:108:0 <- src/test.ts:64177:21)
at CompiledTemplate.proxyViewClass.DebugAppView.createHostView (webpack:///~/@angular/core/src/linker/view.js:564:0 <- src/test.ts:64633:52)
at ComponentFactory.create (webpack:///~/@angular/core/src/linker/component_factory.js:202:0 <- src/test.ts:33107:25)