私は、Angular 2プロジェクトでジャスミンを使って統合テストを作成しようとしています。サービスとデータを模擬して適切な単体テストを実行することができますが、今ではコンポーネントでサービスを使用して実際にバックエンドAPIに接続できることを確認したいと考えています。これまでのところ、コンポーネントとサービスの両方のメソッドがスパイからトリガーされていることを確認できますが、コンポーネント内の.subscribe(....)メソッドはテストが終了するまで完了しません。次のように私の仕様のための私のコードは次のとおりです。Angular 2モックなしで観測可能なコンポーネントをテストする
import { async, ComponentFixture, TestBed, inject, fakeAsync } from '@angular/core/testing';
import { DebugElement } from "@angular/core";
import { By } from "@angular/platform-browser";
import { ReviewComponent } from './review.component';
import { FormsModule } from '@angular/forms';
import { UrlService } from 'app/shared/services/url.service';
import { HttpModule, Http } from '@angular/http';
import { ReviewService } from "./review.service";
describe('CommunicationLogComponent',() => {
let component: ReviewComponent;
let fixture: ComponentFixture<ReviewComponent>;
let serviceSpy: jasmine.Spy;
let componentSpy: jasmine.Spy;
let service: ReviewService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormsModule, HttpModule],
providers: [UrlService],
declarations: [ReviewComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ReviewComponent);
component = fixture.componentInstance;
component.processId = 6;
service = fixture.debugElement.injector.get(ReviewService);
componentSpy = spyOn(component, "ngOnInit").and.callThrough();
serviceSpy = spyOn(service, 'getReviewByProcess').and.callThrough();
});
it('should create component',() => {
expect(component).toBeTruthy();
});
it('should not have called ngOnInit() yet',() => {
expect(componentSpy).not.toHaveBeenCalled();
});
it('should make a call to ngOnInit() and by extension getReviewByProcess',() => {
fixture.detectChanges();
expect(componentSpy).toHaveBeenCalled();
expect(serviceSpy).toHaveBeenCalled();
});
//ISSUES HERE
it('should show review after the getReviewByProcess resolves', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(componentSpy).toHaveBeenCalled();
fixture.detectChanges();
expect(component.Reviews[0]).not.toBe(undefined);
});
}), 5000);
});
アップ全ての試験は「HERE //問題」でマークされた1が正常に動作し、合格するまで。
私はasync()を使用して、テストを終了する前にフィクスチャが安定するのを待っています。また、componentSpyを介して、ngOnInitが呼び出されたことが確認されます(バックエンドに接続してレビューに登録します)。
マイコンポーネントのコードは次のようになります。
import { Component, EventEmitter, Input, OnInit } from '@angular/core';
//Service
import { ReviewService } from "app/process/monitoring/shared/components/review/review.service";
//Classes
import { Review } from "app/process/monitoring/shared/components/review/review";
@Component({
providers: [
ReviewService
],
selector: 'monitoring-review',
templateUrl: './review.component.html',
styleUrls: ['./review.component.css']
})
export class ReviewComponent implements OnInit {
public Review: Review = new Review();
public Reviews: Review[] = [];
@Input() public processId: number;
constructor(
private ReviewService: ReviewService
) { }
ngOnInit(): void {
this.ReviewService.getReviewByProcess(this.processId, true).first().subscribe(
Reviews => {
if (Reviews) {
this.Reviews = Reviews //doesn't trigger until test is finished
}
},
error => console.log(error)
);
}
}
そして最後に、私のReviewServiceは次のようになりますカルマのデバッガを使用して
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Headers, RequestOptions, RequestMethod, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
// App-wide Services
import { UrlService } from 'app/shared/services/url.service';
// Classes
import { Review } from "app/process/monitoring/shared/components/review/review";
@Injectable()
export class ReviewService {
private devUrl: string;
private jsonHeaders: Headers = new Headers({ 'Content-Type': 'application/json' });
private prodUrl: string;
private reviewPath: string = 'monitoring/program/';
constructor(
private urlService: UrlService,
private http: Http
) {
this.devUrl = this.urlService.getUrl('dev').url;
this.prodUrl = this.urlService.getUrl('prod').url;
}
getReviewByProcess(processId: number, isProd: boolean = false): Observable<Review[]> {
let targetUrl: string = (isProd ? this.prodUrl : this.devUrl) + this.reviewPath + "/" + processId;
return this.http.get(targetUrl, { withCredentials: true })
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error')
);
};
}
、私は私のテストはどのそして、ngOnInitを呼び出すことを確認することができますこのサービスへの呼び出しは、テストが完了するまで、購読しているコンポーネントの内部(「//はトリガーしません」とマークされています)に当たることはありません。
要約:「ライブ」バックエンドを使用してデータを収集するサービスと統合するコンポーネントをテストできるテストを作成したいと考えています。それはサービスであり、私のコンポーネントは何も嘲笑しません。私のメソッドに到達したが、私のReviewComponentのngOnInit()メソッドで見つかったサブスクライブ(...)は、テストが完了するか失敗するまで終了しない。
モックデータは返信したくないのですが、私のウェブAPIから正当なデータを返すことはできません。これはジャスミンがサポートできないものですか?分度器を使って解決策を探すべきですか? – LandSharks
これは単体テストであり、スコープで特定のコンポーネント/機能専用であり、環境をモックしてアーカイブする必要があります。 httpをモックする場合は、MockBackendを使用してhttpサービスレベルを模擬することができます。 Web APIを使用してエンドツーエンドテスト用のテスト用の分度器を呼び出す必要があるが、角度2のユニットテストの優れた機能があれば、e2eの必要性はそれほどありません。 –
Jasmineは統合テストをサポートしていませんか?私は角度2のためのメインのドキュメンタリーサイトに気づいた:https://angular.io/docs/ts/latest/guide/testing.html#!#component-with-async-service 彼らは私が正確なことをやっていること私は気づいたhttp接続を望んでいません。彼らのオブジェクトには静的なデータがありました。 – LandSharks