Skip to content

Latest commit

 

History

History
84 lines (68 loc) · 3.52 KB

mocking-dependencies.md

File metadata and controls

84 lines (68 loc) · 3.52 KB

Mocking Dependencies

Since we want to isolate our service testing from outside network requests, we have to create mock requests where we can manually set up properties like expected responses, errors, headers, etc. Fortunately Angular 2 makes this an easy process by providing a way to make fake HTTP calls through the MockBackend class. This class can be injected wherever a service is expecting the HTTP module and used by the service as though it were the real HTTP module - except now the results/data are set up by us, without any network request taking place. Let's take a look at some code:

wikisearch.ts

import {Http} from '@angular/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';


@Injectable()
export class SearchWiki {
  constructor (private http: Http) {}

  search(term: string): Observable<any> {
    return this.http.get(
      'https://en.wikipedia.org/w/api.php?' +
      'action=query&list=search&srsearch=' + term
    ).map((response) => response.json());
  }

  searchXML(term: string): Observable<any> {
    return this.http.get(
      'https://en.wikipedia.org/w/api.php?' +
      'action=query&list=search&format=xmlfm&srsearch=' + term
    );
  }
}

Here is a basic service. It will query Wikipedia with a search term and return an Observable with the results of the query. The search function will make a GET request with the supplied term, and the searchXML method will do the same thing, except request the response to be in XML instead of JSON. As you can see, it depends on the HTTP module to make a request to wikipedia.org. We want to use MockBackend to inject a mocked version of HTTP, so that any call to http.get will allow us to feed in whatever data we want - not the data from wikipedia.org. Lets take a look at our unit test:

wikisearch.spec.ts

import {
  BaseRequestOptions,
  Response,
  ResponseOptions,
  ConnectionBackend,
  Http
} from '@angular/http';

import {
  it,
  expect,
  describe,
  beforeEachProviders,
  inject
} from '@angular/core/testing';

import {MockBackend} from '@angular/http/testing';
import {provide} from '@angular/core';
import {SearchWiki} from './wikisearch';

describe('Testing the wikipedia search service', () => {
  beforeEachProviders(() => {
    return [
      MockBackend,
      BaseRequestOptions,
      SearchWiki,
      provide(
        Http, {
          useFactory: (
            mockbackend: ConnectionBackend,
            defaultOptions: BaseRequestOptions
          ) => {
            return new Http(mockbackend, defaultOptions);
          },
          deps: [MockBackend, BaseRequestOptions]
        }
      )
    ];
  });
});

As you can see, we have quite a few imports here to set up our mocked HTTP module. We use beforeEachProviders to include MockBackend to create our mocked HTTP module. In order to properly set up our mocked module we also include BaseRequestOptions and ConnectionBackend. We create an instance of Http that our service will get by using a factory.

To create this instance the Http class takes two parameters: the back-end to use (ConnectionBackend type) and the default options to use (RequestOptions type). Since we are planning to use a mock back-end, we feed in MockBackend to the first parameter. The second parameter, default options, doesn't have any bearing on the mocking aspects we plan on using, so we use BaseRequestOptions, which is the default implementation.

Right now this test doesn't do anything aside from setting up a mockable HTTP module - let's take a look at some actual tests.