How can a mock a http observable in Angular2 for when no api is written

11,289

Update 1

From https://angular.io/guide/deprecations#http

@ANGULAR/HTTP/TESTING CLOSEST REPLACEMENT IN @ANGULAR/COMMON/HTTP/TESTING
MockBackend ==> HttpTestingController
MockConnection ==> HttpTestingController

Original

You can use MockBackend

import {BaseRequestOptions, Http} from '@angular/http';
import {MockBackend} from '@angular/http/testing';
it('should get some data', inject([AsyncTestCompleter], (async) => {
  var connection;
  var injector = Injector.resolveAndCreate([
    MockBackend,
    {provide: Http, useFactory: (backend, options) => {
      return new Http(backend, options);
    }, deps: [MockBackend, BaseRequestOptions]}]);
  var http = injector.get(Http);
  var backend = injector.get(MockBackend);
  //Assign any newly-created connection to local variable
  backend.connections.subscribe(c => connection = c);
  http.request('data.json').subscribe((res) => {
    expect(res.text()).toBe('awesome');
    async.done();
  });
  connection.mockRespond(new Response('awesome'));
}));

Update

Define the dummyData like:

private dummyData = {
  json: function() {
    return [
      {
        id: 1,
        title: 'Title 1',
        content: 'content 1',
        author: 'author 1'
      },
      {
        id:2,
        title: 'Title 2',
        content: 'content 2',
        author: 'author 1'
      }
    ]};
}
Share:
11,289

Related videos on Youtube

jonnie
Author by

jonnie

Updated on September 15, 2022

Comments

  • jonnie
    jonnie over 1 year

    I'm new to both Angular2 and Rxjs and I am a little confused about a particular case.

    I have a simple service:

    import { Injectable } from '@angular/core';
    import { Observable, Subject } from 'rxjs/Rx';
    import { Http, Response } from '@angular/http';
    
    export interface Article {
      id: number;
      title: string;
      content: string;
      author: string;
    }
    
    @Injectable()
    export class ArticleService {
      private _articles$: Subject<Article[]>;
      private baseUrl: string;
      private dataStore: {
        articles: Article[]
      };
      constructor(private http: Http) {
        this.baseUrl = 'http://localhost:3000'
        this.dataStore = { articles: [] };
        this._articles$ = <Subject<Article[]>>new Subject();
      }
      get articles$(){
        return this._articles$.asObservable();
      }
    
      loadAll(){
        //Observable.from(this.dummyData)
        this.http.get(`${this.baseUrl}/articles`)
        .map(response => response.json())
        .subscribe(data => {
          //debugger;
          this.dataStore.articles = data;
           // Push a new copy of our article list to all Subscribers.
          this._articles$.next(this.dataStore.articles)
        }, error => console.log('Could not load Articles'));
      }
    }
    

    And this works as expected , but what I would like to do is to be able to develope my service without a api endpoint and using an Observable that I can later swap out for the http.request . I tried to do this using Observable.from to convert a dummy data array to an observable but I get the errors

    Type '{ id: number; title: string; content: string; author: string; }' is not assignable to type 'Article[]'

    I believe this is because it is returning each item separately instead of the array , can someone point me in the correct direction of how this should work

    Update: for clarity the dummyData look like:

    private dummyData = [
          {
            id: 1,
            title: 'Title 1',
            content: 'content 1',
            author: 'author 1'
          },
          {
            id:2,
            title: 'Title 2',
            content: 'content 2',
            author: 'author 1'
          }
        ];
    
  • jonnie
    jonnie almost 8 years
    this would be perfect for testing and maybe my question is not clear enough (I will correct this) but what I would like to do is create an Observable from the Dummy data that can use the same subscribe as the http request
  • Günter Zöchbauer
    Günter Zöchbauer almost 8 years
    What Observable can not use the same subscribe? You mean that you can get the payload using data.json(). What's the purpose? You could also use MockBackend in normal code or InMemoryBackendService used in angular.io/docs/ts/latest/tutorial/toh-pt6.html
  • jonnie
    jonnie almost 8 years
    I was trying to use Observable.from(this.dummyData) instead of this.http.get('${this.baseUrl}/articles').map(..) but get the Type error mentioned in question
  • Günter Zöchbauer
    Günter Zöchbauer almost 8 years
    An object is not assignable to an array of objects. Add your data in an array and pass the array.
  • jonnie
    jonnie almost 8 years
    sorry if this is silly question but am I not doing that with Observable.from(this.dummyData) ? this.summyData is an array.
  • jonnie
    jonnie almost 8 years
    so with your addition and a change from Observable.from(this.dummyData) to Observable.create(()=> { return this.dummyData} ) I was able to get the result I wanted. Thank you
  • Partha Sarathi Ghosh
    Partha Sarathi Ghosh over 7 years
    Hi all, I have same kind of problem. But here I am trying to create environment sensitive mock. Here is my another question with same context. Please help. stackoverflow.com/questions/41634007/…
  • bob
    bob about 7 years
    Things might have changed. Using Angular 2.4.0, rxjs 5.1.0, this worked for me: Observable.create(observer => { observer.next(this.dummyData); });