使用提供程序测试组件
Test component with a providers
我有一个服务 SoundPanelService 用于服务隔离场景(如 https://angular.io/guide/hierarchical-dependency-injection#scenario-service-isolation )
@Injectable()
export class SoundPanelService {
recorded = new Subject<Sound>();
constructor() {
}
}
我有 SoundPanelComponent
Component({
selector: 'app-sound-panel',
templateUrl: './sound-panel.component.html',
styleUrls: ['./sound-panel.component.css'],
providers: [SoundPanelService] // Service isolation
})
export class SoundPanelComponent implements OnInit {
recorded = new Subject<Sound>();
constructor(private soundPanelService: SoundPanelService) {
this.soundPanelService.recorded.subscribe((data) => {
this.recorded.next(data);
});
}
ngOnInit() {
}
}
声音-panel.component.html
<app-sound-player></app-sound-player>
<app-sound-recorder></app-sound-recorder>
SoundPlayer 和 SoundRecorder 通过服务 SoundPanelService 与 soundpanel 通信。
我想测试 SoundPanelComponent
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { SoundPanelComponent } from './sound-panel.component';
import { SoundRecorderComponent } from '../sound-recorder/sound-recorder.component';
import { SoundPlayerComponent } from '../sound-player/sound-player.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { SoundPanelService } from 'src/app/_services/sound-panel.service';
import { Sound } from 'src/app/_models/Sound';
describe('SoundPanelComponent', () => {
let component: SoundPanelComponent;
let fixture: ComponentFixture<SoundPanelComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
SoundPanelComponent,
SoundPlayerComponent,
SoundRecorderComponent,
SafeHtmlPipe
],
imports: [HttpClientTestingModule],
providers: [
{
provide: SoundPanelService, useClass: SoundPanelService
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SoundPanelComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should emit sound on new record from sound panel service', async () => {
const s: Sound = {base64: 'data:base64', mimeType: 'audio/wmw'};
spyOn(component.recorded, 'next').and.callThrough();
sps = TestBed.get(SoundPanelService);
sps.recorded.next(s);
fixture.detectChanges();
fixture.whenStable().then(res => {
expect(component.recorded.next).toHaveBeenCalledTimes(1);
});
});
});
但我收到错误
SoundPanelComponent > 应该在声音面板服务的新记录上发出声音
下一个预期的间谍已被调用一次。被调用0次
如果我让 SoundPanelService providedIn: 'root' 我设法通过了测试,但这不是我想要的,因为我希望 SoundPanelService 与每个 SoundPanelComponent 及其子组件隔离(我打算有很多 SoundPanelComponents在同一页上)。
如何测试这个?
已解决
用过这个Override component providers
必须将代码更改为:
- 引入了 .overrideComponent
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
SoundPanelComponent,
SoundPlayerComponent,
SoundRecorderComponent,
SafeHtmlPipe
],
imports: [HttpClientTestingModule]
})
.overrideComponent(SoundPanelComponent, {
set: {
providers: [
{ provide: SoundPanelService, useClass: SoundPanelService}
]
}
})
.compileComponents();
}));
- 从调试元素获取 SoundPanelService:
it('should emit sound on new record from sound panel service', async () => {
const s: Sound = {base64: 'data:base64', mimeType: 'audio/wmw'};
spyOn(component.recorded, 'next').and.callThrough();
sps = fixture.debugElement.injector.get(SoundPanelService) as SoundPanelService;
sps.recorded.next(s);
fixture.detectChanges();
fixture.whenStable().then(res => {
expect(component.recorded.next).toHaveBeenCalledTimes(1);
});
});
测试通过!
我有一个服务 SoundPanelService 用于服务隔离场景(如 https://angular.io/guide/hierarchical-dependency-injection#scenario-service-isolation )
@Injectable()
export class SoundPanelService {
recorded = new Subject<Sound>();
constructor() {
}
}
我有 SoundPanelComponent
Component({
selector: 'app-sound-panel',
templateUrl: './sound-panel.component.html',
styleUrls: ['./sound-panel.component.css'],
providers: [SoundPanelService] // Service isolation
})
export class SoundPanelComponent implements OnInit {
recorded = new Subject<Sound>();
constructor(private soundPanelService: SoundPanelService) {
this.soundPanelService.recorded.subscribe((data) => {
this.recorded.next(data);
});
}
ngOnInit() {
}
}
声音-panel.component.html
<app-sound-player></app-sound-player>
<app-sound-recorder></app-sound-recorder>
SoundPlayer 和 SoundRecorder 通过服务 SoundPanelService 与 soundpanel 通信。
我想测试 SoundPanelComponent
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { SoundPanelComponent } from './sound-panel.component';
import { SoundRecorderComponent } from '../sound-recorder/sound-recorder.component';
import { SoundPlayerComponent } from '../sound-player/sound-player.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { SoundPanelService } from 'src/app/_services/sound-panel.service';
import { Sound } from 'src/app/_models/Sound';
describe('SoundPanelComponent', () => {
let component: SoundPanelComponent;
let fixture: ComponentFixture<SoundPanelComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
SoundPanelComponent,
SoundPlayerComponent,
SoundRecorderComponent,
SafeHtmlPipe
],
imports: [HttpClientTestingModule],
providers: [
{
provide: SoundPanelService, useClass: SoundPanelService
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SoundPanelComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should emit sound on new record from sound panel service', async () => {
const s: Sound = {base64: 'data:base64', mimeType: 'audio/wmw'};
spyOn(component.recorded, 'next').and.callThrough();
sps = TestBed.get(SoundPanelService);
sps.recorded.next(s);
fixture.detectChanges();
fixture.whenStable().then(res => {
expect(component.recorded.next).toHaveBeenCalledTimes(1);
});
});
});
但我收到错误
SoundPanelComponent > 应该在声音面板服务的新记录上发出声音 下一个预期的间谍已被调用一次。被调用0次
如果我让 SoundPanelService providedIn: 'root' 我设法通过了测试,但这不是我想要的,因为我希望 SoundPanelService 与每个 SoundPanelComponent 及其子组件隔离(我打算有很多 SoundPanelComponents在同一页上)。
如何测试这个?
已解决
用过这个Override component providers
必须将代码更改为:
- 引入了 .overrideComponent
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
SoundPanelComponent,
SoundPlayerComponent,
SoundRecorderComponent,
SafeHtmlPipe
],
imports: [HttpClientTestingModule]
})
.overrideComponent(SoundPanelComponent, {
set: {
providers: [
{ provide: SoundPanelService, useClass: SoundPanelService}
]
}
})
.compileComponents();
}));
- 从调试元素获取 SoundPanelService:
it('should emit sound on new record from sound panel service', async () => {
const s: Sound = {base64: 'data:base64', mimeType: 'audio/wmw'};
spyOn(component.recorded, 'next').and.callThrough();
sps = fixture.debugElement.injector.get(SoundPanelService) as SoundPanelService;
sps.recorded.next(s);
fixture.detectChanges();
fixture.whenStable().then(res => {
expect(component.recorded.next).toHaveBeenCalledTimes(1);
});
});
测试通过!