Sadar Ali
Sadar Ali

Reputation: 153

Testing an API call in Angular 2

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

Answers (1)

malifa
malifa

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

Related Questions