web-dev-qa-db-ja.com

ユニットテストの方法Angular 2つのルーティングパラメータ

ルートの一部から取得したパラメーターを取得するコンポーネントを単純に単体テストしたいとします。たとえば、私のコンポーネントの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();
  });
});
5
Arwin

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() }

インスタンス化に注意してください。

6
Paul Samsotha

誰かがAngular 7でこの問題を抱えることになった場合、Angularドキュメントは、ActivatedRouteサービスに依存するコンポーネントをテストする方法の明確な例を示しています https ://angular.io/guide/testing#activateroutestub 。上記の応答とは少し異なります。

2
Marius Lazar