Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I provide mocked services for development (not testing) in Angular 2?

Tags:

angular

I need a way to mock my services during development (not during testing) in Angular 2. The reason being is that the REST-ful server is not reliable (changing API without notification, not stable, and difficult to wipe and stand up again). It would be nice if I can just mock my services (which are all basically HTTP REST clients).

What's the best approach for creating mock backend services in Angular 2? I get a lot of internet results for mocking backend services with respect to testing, but this context is not my use-case (I am not mocking to test but to develop).

I've used the angular cli to create and scaffold my project and I'm not sure if that tool can help out.

I'm looking for an approach like Spring where we can annotate components/classes with "profiles" and then conveniently specify which profile is active to get the right dependencies injected.

like image 714
Jane Wayne Avatar asked Jan 25 '17 12:01

Jane Wayne


People also ask

How do I mock an Angular service?

To test a service, you set the providers metadata property with an array of the services that you'll test or mock. content_copy let service: ValueService; beforeEach(() => { TestBed. configureTestingModule({ providers: [ValueService] }); }); Then inject it inside a test by calling TestBed.

What is mocking in Angular?

A mock component in Angular tests can be created by MockComponent function. The mock component respects the interface of its original component, but all its methods are dummies. To create a mock component, simply pass its class into MockComponent function.

What is SpyOn in Angular unit testing?

SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result.


1 Answers

I think the best approach to achieve your goal is to use interfaces and a service provider. I hope the following example code can point you in the right direction:

data-tables.service-interface.ts

export interface DataTablesServiceInterface {
    getHeaders(): Promise<any[]>;
    getData(query?: string, offset?: number, size?: number): Promise<any>;
}

data-tables.service-provider.ts

import { Http } from '@angular/http';
import { OpaqueToken } from '@angular/core';

import { DataTablesServiceInterface } from './data-tables.service-interface';
import { DataTablesService } from './data-tables.service';
import { DataTablesMockService } from './data-tables.mock-service';

import { environment } from '../../../environments/environment';

let dataTablesServiceFactory = (http: Http) => {
    var serviceToReturn: DataTablesServiceInterface;
    if (environment.production) {
        serviceToReturn = new DataTablesService(http);
    } else {
        serviceToReturn = new DataTablesMockService();
    }
    return serviceToReturn;
};

export let dataTablesToken = new OpaqueToken('DataTablesServiceInterface');

export let dataTablesServiceProvider =
    {
        provide: dataTablesToken,
        useFactory: dataTablesServiceFactory,
        deps: [
            Http
        ]
    };

You just need to implement the actual and mock service and can provide them depending on the embedded profile mechanism already implemented in angular-cli by use of environment.

Edit: There are a few more information I forgot to mention. In your responsible module you need to declare dataTablesServiceProvider as provider. In the components where you want to use the service, the approach of DI varies slightly from the standard approach.

In the constructor of the component you write the following:

constructor(@Inject(dataTablesToken) private dataTablesService: DataTablesServiceInterface)

If you are interested in opaque tokens, I would suggest a look at Opaque Token by Angular

like image 130
alex kucksdorf Avatar answered Oct 13 '22 01:10

alex kucksdorf