【发布时间】:2019-09-21 22:42:17
【问题描述】:
我一直在尝试为我的 Angular 组件编写单元测试。目前在我的服务调用中以获取我的组件的数据,我有一个 observable,一旦调用完成,它就会被赋予 true。在我的组件中订阅了这个 observable,因此组件知道调用何时完成。我已经设法在我的组件中模拟了对数据的调用,但我正在努力寻找一种方法来模拟单个可观察值。
我能找到的关于 SO 的所有问题都是关于从组件中的服务模拟函数调用,但我找不到关于模拟单个 observable 的问题。
这是我在服务中的函数调用。正如你所看到的,一旦finalize 函数运行,observable 就会被赋予一个新值:
public getSmallInfoPanel(key: string): BehaviorSubject<InfoPanelResponse> {
if (key) {
this.infoPanel = new BehaviorSubject<InfoPanelResponse>(null);
this.http.get(`${this.apiUrl}api/Panels/GetInfoPanel/${key}`).pipe(
retry(3),
finalize(() => {
this.hasLoadedSubject.next(true);
}))
.subscribe((x: InfoPanelResponse) => this.infoPanel.next(x));
}
return this.infoPanel;
}
这是我在服务中创建Observable 的方式:
private hasLoadedSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public hasLoadedObs: Observable<boolean> = this.hasLoadedSubject.asObservable();
然后在我的组件中订阅从BehaviourSubject 创建的Observable:
public hasLoaded: boolean;
ngOnInit() {
this.infoPanelSmallService.hasLoadedObs.subscribe(z => this.hasLoaded = z);
}
当我运行ng test 时,组件测试失败,因为它不知道hasLoadedObs 是什么所以它无法订阅它。
如果我能提供更多信息,请告诉我。谢谢。
更新 1
describe('InformationPanelSmallComponent', () => {
let component: InformationPanelSmallComponent;
let fixture: ComponentFixture<InformationPanelSmallComponent>;
let mockInfoPanelService;
let mockInfoPanel: InfoPanel;
let mockInfoPanelResponse: InfoPanelResponse;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule,
FontAwesomeModule,
HttpClientTestingModule
],
declarations: [InformationPanelSmallComponent, CmsInfoDirective],
providers: [
{ provide: InfoPanelSmallService, useValue: mockInfoPanelService }
]
})
.compileComponents();
}));
beforeEach(() => {
mockInfoPanel = {
Title: 'some title',
Heading: 'some heading',
Description: 'some description',
ButtonText: 'some button text',
ButtonUrl: 'some button url',
ImageUrl: 'some image url',
Key: 'test-key',
SearchUrl: '',
VideoUrl: ''
}
mockInfoPanelResponse = {
InfoPanel: mockInfoPanel
}
fixture = TestBed.createComponent(InformationPanelSmallComponent);
component = fixture.componentInstance;
mockInfoPanelService = jasmine.createSpyObj(['getSmallInfoPanel']);
component = new InformationPanelSmallComponent(mockInfoPanelService);
component.key = "test-key"
});
it('should create', () => {
expect(component).toBeTruthy();
});
//TO DO
it('should get info panel from info panel service', () => {
mockInfoPanelService.getSmallInfoPanel.and.returnValue(of(mockInfoPanelResponse));
component.ngOnInit();
expect(mockInfoPanelService.getSmallInfoPanel).toHaveBeenCalled();
expect(component.infoPanel).toEqual(mockInfoPanel);
});
});
【问题讨论】:
-
为其添加间谍:
spyOnProperty(component.infoPanelSmallService, 'hasLoadedObs', 'get').and.returnValue(of(true)) -
@enno.void 它仍然说
hasLoadedObs未定义。 -
@DanielBailey 您是在嘲笑这项服务,还是在您的 TestBed 中提供您的原始服务?
-
你能分享你的测试文件吗
-
@RuiMarques 经过更多测试后,它看起来与我将内容放入测试文件并从服务中模拟内容的顺序有关。我现在将发布答案。
标签: angular typescript unit-testing jasmine