Testing Component with Service (Promise) in Angular

To perform unit testing on a component that makes use of a service, that returns a promise, we can use fakeAsync() and spy() methods from Angular’s unit testing package.


import { Component, OnInit } from '@angular/core';

import { UserService } from './user.service';

  selector: 'user-name',
  templateUrl: './user.component.html',
  styleUrls:  ['./user.component.scss']
export class UserComponent  implements OnInit {
  userName = '';
  constructor(private userService: UserService) { }

  ngOnInit(): void {
    this.userService.getUserName().then(response => this.userName = response);


import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import 'rxjs/add/operator/toPromise';

export class UserService {

 constructor(private http: HttpClient) {

  getUserName(): Promise<String> {
    return this.http.get('http://localhost:3000/user/')


<div class="user">

By default in the angular testing framework, changes in data aren’t reflected in the template (view) by default unless detectChanges( ) is explicitly called on the component.


import { async, fakeAsync, tick, ComponentFixture, TestBed } from '@angular/core/testing';
import { By }              from '@angular/platform-browser';
import { DebugElement }    from '@angular/core';

import { UserComponent } from './user.component';
import { UserService } from './user.service';

beforeEach(async(() => {
     declarations: [ UserComponent ],
     providers:    [ UserService ]
   .compileComponents(); // compile external template and scss

// Synchronous section
beforeEach(() => {
  fixture = TestBed.createComponent(UserComponent);
  comp    = fixture.componentInstance;

  // Inject UserService into the component
  userService = fixture.debugElement.injector.get(UserService);

  // Setup spy on the `getUserName` method
  spy = spyOn(userService, 'getUserName')

  // Get the Username element from the template DOM structure
  un = fixture.debugElement.query(By.css('.user'));
  elem = un.nativeElement;

it('should show username upon call return', fakeAsync(() => {
  fixture.detectChanges();  // update view with data
  tick();                   // wait for all asynchronous calls to complete
  fixture.detectChanges();  // update view with data


tick( ) also takes milliseconds as argument, to wait for that time instead of waiting for all async calls to return.