I have been trying to write unit tests for my Angular component. Currently in my service call to get the data for my component I have an observable that is given true once the call has finished. This observable to subscribed to in my component so the component knows when the call has bee completed. I have managed to mock the call for data in my component but I am struggling to find a way to mock the single observable value.
All the questions on SO that I can find are all about mocking a function call from the service in the component but none that I can find are about mocking a single observable.
Here is my function call in the service. As you can see the observable is given a new value once the finalize
function runs:
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;
}
Here is how I created the Observable
in the service:
private hasLoadedSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public hasLoadedObs: Observable<boolean> = this.hasLoadedSubject.asObservable();
Then in my component I subscribe to the Observable
created from the BehaviourSubject
:
public hasLoaded: boolean;
ngOnInit() {
this.infoPanelSmallService.hasLoadedObs.subscribe(z => this.hasLoaded = z);
}
When I run ng test
the component test fails because it does not know what hasLoadedObs
is so it cannot subscribe to it.
Let me know if I can provide more info. Thank you.
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);
});
});
spyOnProperty(component.infoPanelSmallService, 'hasLoadedObs', 'get').and.returnValue(of(true))
– enno.voidhasLoadedObs
is undefined. – Daniel Bailey