Struggling to write unit tests for my Angular component, particularly in mocking a single observable value. The service call retrieves data for the component using an observable that is set to true once the call is complete. I have successfully mocked the data call in the component but need help with the single observable.
Most questions on SO focus on mocking function calls from the service rather than a single observable. Here's the function call in the service where the observable gets a new value:
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;
}
I created the Observable in the service like this:
private hasLoadedSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public hasLoadedObs: Observable<boolean> = this.hasLoadedSubject.asObservable();
In the component, I subscribe to the Observable derived from the BehaviorSubject:
public hasLoaded: boolean;
ngOnInit() {
this.infoPanelSmallService.hasLoadedObs.subscribe(z => this.hasLoaded = z);
}
During testing with ng test
, the failure occurs because the component doesn't recognize hasLoadedObs
and cannot subscribe to it.
If more information is needed, please let me know. Thanks!
UPDATE 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);
});
});