Reputation: 153
I have the following 2 components and a single service that is shared by both. I need to unit test them but I'm unable to figure out how to test the dependency of the service on the following components.
//a.component.ts
import { Component, Input } from '@angular/core';
import { Http, Response } from '@angular/http';
import { SharedService } from './shared/shared.service';
@Component({
selector: 'a',
providers: [],
templateUrl: './a.component.html'
})
export class AComponent {
ax = {};
constructor(public helperService: SharedService) {
helperService.getFromAPI().subscribe(data => this.ax = data["people"]);
}
}
//b.component.ts
import { Component } from '@angular/core';
import { SharedService } from './shared/shared.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'b',
providers: [],
templateUrl: './b.component.html'
})
export class BComponent {
subscription: Subscription;
x = '';
constructor(public helperService: SharedService) {}
ngOnInit() {
this.subscription = this.helperService.c$.subscribe(
data => {
this.x = data;
});
}
}
This is the service that calls the API. The other function setC
add the value to the observable upon a button click and this value is to be accessed by the BComponent
.
// shared.service
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
@Injectable()
export class SharedService {
private c = new Subject<string>();
c$ = this.c.asObservable();
constructor(
private http: Http
) { }
getFromAPI() {
return this.http.get('url')
.map((res: Response) => res.json());
}
setC(data: string) {
this.c.next(data);
}
}
How can I test this in Jasmine? So far, my efforts have been futile.
I've tried doing like
it('xxx', inject([SharedService], (service: SharedService) => {
const fixture = TestBed.createComponent(AComponent);
const app = fixture.componentInstance;
spyOn(service, 'c$').and.callThrough;
service.setC('Random Name');
expect(service.c$).toHaveBeenCalled();
}));
This fails the test with Expected spy c$ to have been called.
.
Upvotes: 4
Views: 2393
Reputation: 8165
You're spying on an Observable
it seems but what's called when you call setC
is the next
function of your Subject. So you probably want to spy on that instead.
Something like spyOn(service.c, 'next').and.callThrough()
should do the trick.
Hope it helps.
Update: If you want explicitely to test the functionality of your Observable
then i would just subscribe to it, call setC
and test the response, something like this:
service.$c.subscribe((data) => {
expect(data).toBe('foobar');
});
service.setC('foobar');
To answer your question in the comment: Since your c
is private you can spy on it like this: spyOn(service['c'], 'next').and.callThrough()
.
It could be that your ide will nag about spying on private methods, in this case you can add the any
type like this: spyOn<any>(...)
Upvotes: 3