vendredi 2 juin 2017

Angular, test, dependency injection, http.get ... Help to understand

First sorry for my english.

I'm using Angular and develop a simple service with his test.

The service load a JSON file with http.get method and store it content in a variable. The aim is not important.

Below a code that works :

First the service

import {Http} from '@angular/http';
import {Injectable} from '@angular/core';
import {Constants} from 'config/constants';
import 'rxjs/Rx';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class LoadJsonFileService {
  private config: Object = null;

  constructor(private http: Http) {
  }

  private loadJsonAndUpdateConfig() {
    this.http
      .get(Constants.CONFIG_FILE_NAME)
      .map(response => response.json())
      .catch((error: any): any => {
        return Observable.throw(error.json().error || 'Server error');
      }).subscribe((configJson) => {
        this.config = configJson;
      });
  }
  public getConfig(key: string): string {
    if (!this.config) {
      this.loadJsonAndUpdateConfig();
    }
    return this.config[key];
  }
}

Then the test :

import {BaseRequestOptions, ConnectionBackend, Http, RequestOptions, Response, ResponseOptions} from '@angular/http';
import {MockBackend, MockConnection} from '@angular/http/testing';
import {LoadJsonFileService} from './load-json-file.service';
import {inject, TestBed} from '@angular/core/testing';

describe('Test suite ...', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        {provide: RequestOptions, useClass: BaseRequestOptions},
        {provide: ConnectionBackend, useClass: MockBackend},
        Http,
        LoadJsonFileService
      ]
    });
  });

  it('The test ...', inject([ConnectionBackend, LoadJsonFileService],
    (backend,
     service: LoadJsonFileService) => {
      backend.connections.subscribe((c: MockConnection) => {
        c.mockRespond(new Response(new ResponseOptions({body: {key: 'foo'}})));
      });

      expect(service.getConfig('key')).toBe('foo');
    }));

});

Test is OK.

The code that don't work and i don't know why :

import {Http} from '@angular/http';
import {Injectable} from '@angular/core';
import {Constants} from 'config/constants';
import 'rxjs/Rx';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class LoadJsonFileService {
  private config: Object = null;

  constructor(private http: Http) {
    this.loadJsonAndUpdateConfig();
  }

  private loadJsonAndUpdateConfig() {
    this.http
      .get(Constants.CONFIG_FILE_NAME)
      .map(response => response.json())
      .catch((error: any): any => {
        return Observable.throw(error.json().error || 'Server error');
      }).subscribe((configJson) => {
        this.config = configJson;
      });
  }
  public getConfig(key: string): string {
    return this.config[key];
  }
}

The difference is the call of this.loadJsonAndUpdateConfig() in the constructor and not in the getConfig method. Test fail :

TypeError: null is not an object (evaluating 'this.config[key]')

When I put some debug the subscribe method is never trigger like if http.get is never call ...

I'm confused is anyone can explain me this behaviour ?

Thanks,

Stef

Aucun commentaire:

Enregistrer un commentaire