2017-06-02 13 views
0

私の英語のために最初に申し訳ありません。角度、テスト、依存性注射、http.get ...理解するための助け

私はAngularを使用しており、彼のテストで簡単なサービスを開発しています。

サービスでは、http.getメソッドを使用してJSONファイルをロードし、そのコンテンツを変数に格納します。 目的は重要ではありません。その後

まずサービス

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]; 
    } 
} 

テスト:動作するコードの下

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'); 
    })); 

}); 

テストはOKです。

動作しないと私は理由を知りませんコード:

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]; 
    } 
} 

差がGETCONFIG方式では、コンストラクタでthis.loadJsonAndUpdateConfigの呼び出し()とではありません。 テストは失敗:http.getは、私は混乱している...

を呼び出すことはありません場合、私は購読方法をデバッグいくつかを置く

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

は次のようにトリガーされることはありません、誰もが私にこの動作を説明することができるのですか?最初のコード例あなたはconfigに何かを割り当てる場合を除いて、動作しないでください。

おかげで、

ステフ

答えて

0

かいつまんでは、ちょうど変数

private config: Object = {}; 

ロングバージョンにデフォルト値を割り当てますthis.config[key]ピースが実行される前(レースコンディション)に、どこか別の場所でバックエンド要求が終了しますが、それがローカルで(またはテストで)動作すると、サーバー上で動作しなくなる可能性があります。

this.config = configJson;の前には、基本的にはgetConfig()が呼び出されます(テンプレートの場合)。 HTTP要求が開始された直後にHTTP要求が「非同期」、つまりjs/ts/angularが完了するまで待機せず、後続のコードが実行されます。

あなたは、それをテストする値を返す前に、非同期タイムアウトを追加したり、より良いInMemoryWebApiModule

+0

おかげで、角度のマニュアルを参照してくださいしたいが、問題は、なぜヌルエラー(これは結果である)でなかった場合は、私のコードだけにあります'loadJsonAndUpdateConfig()'メソッドがコンストラクタで呼び出されたときに 'http.get'メソッドが呼び出されない理由を説明しますが、' getConfig'メソッドに配置すると呼び出されます。 – Wilda