Reputation: 247
I'm new to testing in Jasmine and Karma and I'm trying to figure out how to test the observable of a component which gets set in the ngOnInit.
I have the following component:
export class Component implements OnInit{
currentConfig$: Observable<Config>;
constructor(
private someService: someService,
private route: ActivatedRoute
){}
ngOnInit() {
this.route.params.subscribe(params => {
this.someService.init(params.name)
})
this.currentConfig = this.someService.config$
}
}
Here's the service:
export class SomeService {
private subject: Subject<Config> = new Subject()
readonly config$ = subject.asObservable()
init(name: string): void {
this.findOne(name).subscribe(res => {
if (res)
this.subject.next({name})
})
}
findOne(name): Observable<any> {
return this.http.get('api');
}
}
And then I can subscribe to the currentConfig observable with the async pipe in the template.
I'm trying to test the values emitted by currentConfig$
of the Component.
Here's what my test looks like now:
fit('should show create component', fakeAsync(() => {
const component = fixture.componentInstance;
const debugElement = fixture.debugElement;
const expected = {name: 'ok'}
// this works
someService.config$.subscribe(config => console.log(config));
// this doesn't work even if I put it after the detect changes
// component.currentConfig$.subscribe(config => console.log(config));
spyOn(someService, 'findOne').and.returnValue(of(expected));
fixture.detectChanges();
}));
The component currentConfig$
is undefined if I try to subscribe to it. Could it be because of the async pipe which consumes the value emitted? Or I'm totally in the wrong direction? And how could I test it then?
I'm also still pretty confused about the spyOn. Should spy on a function of the service that deep inside of the ngOnInit?
EDIT
I think I solved it. I had to call component.ngOnInit()
instead of fixture.detectChanges()
, then subscribe to the component observable and then call fixture.detectChanges()
.
Here's the final test working:
fit('should get room config given room name', fakeAsync(() => {
const component = fixture.componentInstance;
const config: Config= {
name: 'name',
};
// mock service response
spyOn(roomService, 'findOne').and.returnValue(of(response));
// call ngOnInit instead. Detect changes keeps observable cold.
component.ngOnInit();
component.roomConfig$.subscribe(config => expect(config).toEqual(roomConfig));
// trigger second change detection.
fixture.detectChanges();
}));
I'm not sure why detectChanges kept the observable cold. If anyone can clear that out?
Upvotes: 3
Views: 3279
Reputation: 12036
ngOnInit is called during first change detection. in your test you could try to call it manually component.ngOnInit()
or, in case if you want to run it in a more like runtime environment - by calling the change detection itself fixture.detectChanges()
Upvotes: 1