ルートの一部から取得したパラメーターを取得するコンポーネントを単純に単体テストしたいとします。たとえば、私のコンポーネントのngOnInitは次のようになります。
ngOnInit() {
this.route.parent.params.switchMap((params: Params) => this.service.getProject(params['projectId']))
.subscribe((project: Project) => this.update(project));
}
どうすればよいですか:1:コンポーネントの作成がまったく機能するようにテストをセットアップして、他のパーツを単体テストできるようにします
回答で編集-サンプルActivatedRouteStubは、監視可能なパラメーターも持つ親で拡張する必要があり、useValueの代わりにuseClassを使用する必要があります(元に戻すのを忘れました):
@Injectable()
export class ActivatedRouteStub {
// ActivatedRoute.params is Observable
private subject = new BehaviorSubject(this.testParams);
params = this.subject.asObservable();
// Test parameters
private _testParams: {};
get testParams() { return this._testParams; }
set testParams(params: {}) {
this._testParams = params;
this.subject.next(params);
}
// ActivatedRoute.snapshot.params
get snapshot() {
return { params: this.testParams };
}
// ActivatedRoute.parent.params
get parent() {
return { params: this.subject.asObservable() };
}
}
2:UnitTestでprojectIdの値を指定しますか?
Angle2ドキュメントの例は、switchMapで機能しないか、まったく機能しないようです(そこからActivatedRouteStubを使用しましたが、これまでのところ運がありません-paramsは常に未定義です)。
回答で編集:
describe('ProjectDetailsComponent', () => {
let component: ProjectDetailsComponent;
let fixture: ComponentFixture<ProjectDetailsComponent>;
let activatedRoute: ActivatedRouteStub;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([{ path: 'projects/:projectId', component: ProjectDetailsComponent }])],
declarations: [ProjectDetailsComponent],
schemas: [NO_ERRORS_SCHEMA],
providers: [{ provide: ProjectsService, useClass: ProjectsServiceStub }, {provide: ActivatedRoute, useClass: ActivatedRouteStub}]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProjectDetailsComponent);
component = fixture.componentInstance;
activatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
activatedRoute.testParams = { projectId: '123'};
fixture.detectChanges();
});
fit('should create', () => {
expect(component).toBeTruthy();
});
});
Paramsが未定義になる唯一の方法は、スタブを正しく作成していない場合です。電話を見てください
this.route.parent.params.switchMap
params
は、2レベルの深さのネストされたプロパティです。したがって、プレーンなJSオブジェクトとして必要になります
let mock = {
parent: {
params: Observable.of(...)
}
}
クラスを使用したい場合は、次のようなものを使用できます
class ActivatedRouteStub {
parent = {
params: Observable.of({})
};
set testParams(params: any) {
this.parent.params = Observable.of(params);
}
}
testParams
のセッターを使用して、parent.params
の値を設定するだけです。したがって、stub.testParams = whatever
を実行すると、値はparent.params
のオブザーバブルに設定されます。
これを実装する方法に関する上記の説明とは別に、構成にもエラーがあります
{provide: ActivatedRoute, useValue: ActivatedRouteStub}
useValue
は、作成するオブジェクトであると想定されています。つまり、クラスを渡すことになり、そのクラスが注入されるものになり、クラスのインスタンスではありません。 Angularで作成する場合は、useClass
を使用する必要があります。それ以外の場合は、インスタンスを自分で作成し、そのインスタンスを値として使用する必要があります。
{provide: ActivatedRoute, useValue: new ActivatedRouteStub() }
インスタンス化に注意してください。
誰かがAngular 7でこの問題を抱えることになった場合、Angularドキュメントは、ActivatedRouteサービスに依存するコンポーネントをテストする方法の明確な例を示しています https ://angular.io/guide/testing#activateroutestub 。上記の応答とは少し異なります。