title: Angular 6: Testing service with httpclient request errors
body: <p>I have a course service that gets its data from a backend server. I'm trying to write a spec to the service and components that request data from it. I only have get requests. I have had a lot of failures and I didn't find anything on google answers.</p>
  
  <p><strong>these are the interfaces</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>export interface ICourse {
    id: number;
    title: string;
    author: string;
    segments: ISegment[];
  }
  
  export interface ISegment {
    id: number;
    unit_id: number;
    unit_title: string;
    name: string;
    type: string;
    data: string;
    questions: IQuestion[];
  }
  
  export interface IQuestion {
    id: number;
    question: string;
    answer1: string;
    answer2: string;
    answer3: string;
    answer4: string;
    correct: number;
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>Course Service Errors:</strong></p>
  
  <pre><code>CourseService getCourses should return all courses
  Error: Expected no open requests, found 1: GET http://localhost:3000/courses.json
  TypeError: Cannot read property 'getCourses' of undefined
  TypeError: Cannot read property 'verify' of undefined
  </code></pre>
  
  <p><strong>Course-List Component Errors:</strong></p>
  
  <pre><code>getCourses should return an Observable&lt;ICourse[]&gt;
  Expected undefined to be truthy.
  
  should create
  [object ErrorEvent] thrown
  </code></pre>
  
  <p><strong>This are the components and the specs:</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// ------ course.service ------ //
  
  import { Injectable } from '@angular/core';
  import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
  import { BehaviorSubject } from 'rxjs';
  
  import { Observable, throwError } from 'rxjs';
  import { catchError, groupBy } from 'rxjs/operators';
  
  import { ICourse } from './course';
  import { HttpErrorHandler, HandleError } from './http-error-handler.service'
  
  // Inject Data from Rails app to Angular app
  @Injectable()
  export class CourseService {
  
    // JSON url to get data from
    private url = 'http://localhost:3000/courses';
    private courseUrl = 'http://localhost:3000/courses.json';
  
  
    constructor(
      private http: HttpClient) { }
  
    // // Handle Any Kind of Errors
    private handleError(error: HttpErrorResponse) {
  
      // A client-side or network error occured. Handle it accordingly.
      if (error.error instanceof ErrorEvent) {
        console.error('An error occured:', error.error.message);
      }
  
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong.
      else {
        console.error(
          'Backend returned code ${error.status}, ' +
          'body was ${error.error}');
      }
  
      // return an Observable with a user-facing error error message
      return throwError(
        'Something bad happend; please try again later.');
    }
  
    // Get All Courses from Rails API App
    getCourses(): Observable&lt;ICourse[]&gt; {
    const coursesUrl = `${this.url}` + '.json';
  
    return this.http.get&lt;ICourse[]&gt;(coursesUrl)
        .pipe(catchError(this.handleError));
    }
  
    // Get Single Course by id. will 404 if id not found
    getCourse(id: number): Observable&lt;ICourse&gt; {
      const detailUrl = `${this.url}/${id}` + '.json';
      return this.http.get&lt;ICourse&gt;(detailUrl)
          .pipe(catchError(this.handleError));
    }
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// ------ course.service.spec ------ //
  
  import { HttpClient, HttpResponse } from '@angular/common/http';
  import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
  import { TestBed, async, getTestBed, ComponentFixture, inject, tick, fakeAsync } from '@angular/core/testing';
  import { DebugElemet } from '@angular/core';
  import { By } from '@angular/platform-browser';
  
  import { CourseService } from './course.service';
  import { ICourse } from './course';
  
  describe('CourseService', () =&gt; {
    let httpClient: HttpClient;
    let httpTestingController: HttpTestingController;
    let courseService: CourseService;
  
  
    // before each test, default value and delete old test
    beforeEach(() =&gt; {
      TestBed.configureTestingModule({
        imports: [HttpClientTestingModule],
        providers: [CourseService]
      });
  
      // Inject the http, test controller, and service-under-test
      // as they will be referenced by each test.
      httpClient = TestBed.get(HttpClient);
      httpTestingController = TestBed.get(HttpTestingController);
      courseService = TestBed.get(CourseService);
    });
  
    // After every test, assert that there are no more pending requests.
    afterEach(() =&gt; {
      httpTestingController.verify();
    });
  
    // ----------- CourseService method tests begin ----------- //
  
    // Test getCourses()
    describe('getCourses', () =&gt; {
        // Mock Data to test the service
        let expectedCourses: ICourse[];
  
        beforeEach(() =&gt; {
          courseService = TestBed.get(CourseService);
          //expectedCourses = courseService.getCourses();
  
          expectedCourses = [
            { id: 1, title: "Angular is Fun", author: "Son Goku", segments: [
              { id: 1, unit_id: 1, unit_title: "Components", name: "Lesson 1: Create Components", type: "Video", data: "www.hellokitty.com/angular1.flv" },
              { id: 2, unit_id: 1, unit_title: "Components", name: "Lesson 2: Decorators", type: "Video", data: "www.hellokitty.com/angular2.flv" },
              { id: 3, unit_id: 1, unit_title: "Components", name: "Lesson 3: Life Cycle", type: "Video", data: "www.hellokitty.com/angular3.flv" } ]
            },
            { id: 2, title: "Ruby on Rails", author: "Monokuma", segments: [
              { id: 4, unit_id: 1, unit_title: "Introduction", name: "Lesson 1: Rails Console", type: "Video", data: "www.sdr2.com/rails1.flv" },
              { id: 5, unit_id: 2, unit_title: "Introduction", name: "Lesson 1: Gems", type: "Video", data: "www.sdr2.com/rails2.flv" } ]
            },
            { id: 3, title: "Java", author: "Hououin Kyouma", segments: [
              { id: 6, unit_id: 1, unit_title: "Data Structures", name: "Lesson 1: Node", type: "Video", data: "www.deathnote.com/java1.flv" },
              { id: 7, unit_id: 1, unit_title: "Data Structures", name: "Lesson 2: Stack", type: "Video", data: "www.deathnote.com/java2.flv" },
              { id: 8, unit_id: 1, unit_title: "Data Structures", name: "Lesson 3: List", type: "Video", data: "www.deathnote.com/java3.flv" }]
            }
          ] as ICourse[];
        });
  
        // Test getCoures()
        it('should return all courses', () =&gt; {
          courseService.getCourses().subscribe(
            courses =&gt; expect(courses).toEqual(expectedCourses))
        });
  
    });
  
    // Test getCourse(id)
    describe('getCourse', () =&gt; {
      // Mock Data to test the service
      let expectedCourse: ICourse;
  
      beforeEach(() =&gt; {
        courseService = TestBed.get(CourseService);
  
        expectedCourse = { id: 3, title: "Java", author: "Hououin Kyouma", segments = [
                          { id: 6, unit_id: 1, unit_title: "Data Structures", name: "Lesson 1: Node", type: "Video", data: "www.deathnote.com/java1.flv" },
                          { id: 7, unit_id: 1, unit_title: "Data Structures", name: "Lesson 2: Stack", type: "Video", data: "www.deathnote.com/java2.flv" },
                          { id: 8, unit_id: 1, unit_title: "Data Structures", name: "Lesson 3: List", type: "Video", data: "www.deathnote.com/java3.flv" }]
                        } as ICourse;
      });
  
      it('should return course by id', () =&gt; {
          courseService.getCourse(3).subscribe(
            courses =&gt; expect(course).toEqual(expectedCourses[2]))
      });
    });
  
  });</code></pre>
  </div>
  </div>
  </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// ----------- course-list.component ----------- //
  
  import { Component, OnInit } from '@angular/core';
  import { ActivatedRoute, Router, Routes } from '@angular/router';
  
  import { ICourse } from '../course';
  import { CourseService } from '../course.service';
  
  
  // Course-list decorator
  @Component({
    selector: 'lg-course-list',
    templateUrl: './course-list.component.html',
    styleUrls: ['./course-list.component.sass']
  })
  
  export class CourseListComponent implements OnInit {
    pageTitle = "Labguru Academy";
    courses: ICourse[] =[];
    errorMessage: string;
  
    constructor(private courseService: CourseService,
          private route: ActivatedRoute,
          private router: Router) {
    }
  
    // Get list of courses from service
    getCourseList() {
      this.courseService.getCourses()
        .subscribe(
          courses =&gt; this.courses = courses,
          errorMessage =&gt; this.errorMessage = &lt;any&gt;Error
        );
    }
  
    // On start of the life cycle
    ngOnInit() {
      this.getCourseList();
    }
  
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// ----------- course-list.component.spec ----------- //
  
  import { async, ComponentFixture, TestBed } from '@angular/core/testing';
  import { RouterTestingModule } from '@angular/router/testing';
  import { HttpClientTestingModule } from '@angular/common/http/testing';
  import { DebugElement } from '@angular/core';
  import { By } from '@angular/platform-browser';
  
  import { CourseService } from '../course.service';
  import { CourseListComponent } from './course-list.component';
  import { ICourse } from './course';
  
  describe('CourseListComponent', () =&gt; {
    let component: CourseListComponent;
    let service: CourseService;
    let fixture: ComponentFixture&lt;CourseListComponent&gt;;
    let de: DebugElement;
  
    beforeEach(async(() =&gt; {
      TestBed.configureTestingModule({
        imports: [ RouterTestingModule, HttpClientTestingModule ],
        declarations: [ CourseListComponent ],
        providers: [ CourseService ]
      })
      .compileComponents();
    }));
  
    beforeEach(() =&gt; {
      service = new CourseService();
      component = new CourseListComponent(service);
    });
  
  
    // Check the title of the course-list page
    it(`should have as title 'Labguru Academy'`, async(() =&gt; {
      fixture = TestBed.createComponent(CourseListComponent);
      component = fixture.debugElement.componentInstance;
      expect(component.pageTitle).toContain('Labguru Academy');
    }));
  
    // Test getCourses()
    describe('getCourses', () =&gt; {
        it('should return an Observable&lt;ICourse[]&gt;', () =&gt; {
          fixture = TestBed.createComponent(CourseListComponent);
          component = fixture.debugElement.componentInstance;
          expect(component.getCourseList()).toBeTruthy();
        });
    });
  
  
    it('should create', () =&gt; {
      expect(component).toBeTruthy();
    });
  });</code></pre>
  </div>
  </div>
  </p>