9

私は、ルートパラメータの変更に応答する角度2のコンポーネントを持っています(メインルートから移動していないため、コンポーネントは最初からリロードされません。部品コード:角度2 - ルートパラメータの変更のテスト

export class MyComponent{ 
    ngOnInit() { 
     this._routeInfo.params.forEach((params: Params) => { 
      if (params['area']){ 
       this._pageToShow =params['area']; 
      } 
     }); 
    } 
} 

これは御馳走を動作し、_pageToShowは、ナビゲーション上の適切な設定されている

私は、ルートへの変更(そう、観察の第2のトリガに動作をテストしようとしているが、それはです私のために働くことを拒否する)。私の試みはここにある:

it('sets PageToShow to new area if params.area is changed', fakeAsync(() => { 
    let routes : Params[] = [{ 'area': "Terry" }]; 
    TestBed.overrideComponent(MyComponent, { 
     set: { 
      providers: [{ provide: ActivatedRoute, 
       useValue: { 'params': Observable.from(routes)}}] 
     } 
    }); 

    let fixture = TestBed.createComponent(MyComponent); 
    let comp = fixture.componentInstance; 
    let route: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute); 
    comp.ngOnInit(); 

    expect(comp.PageToShow).toBe("Terry"); 
    routes.splice(2,0,{ 'area': "Billy" }); 

    fixture.detectChanges(); 
    expect(comp.PageToShow).toBe("Billy"); 
})); 

しかし、これを実行すると、例外としてTypeError: Cannot read property 'subscribe' of undefinedがスローされます。 fixture.detectChanges();行なしで実行すると、2番目の期待通りに失敗します。

答えて

14

まず、Observableの代わりにSubjectを使用してください。 observableは1回だけ購読されます。したがって、最初のパラメータセットのみを出力します。 Subjectを使用すると、アイテムを放置したままにすることができ、単一のサブスクリプションでアイテムが引き続き取得されます。

let params: Subject<Params>; 

beforeEach(() => { 
    params = new Subject<Params>(); 
    TestBed.configureTestingModule({ 
    providers: [ 
     { provide: ActivatedRoute, useValue: { params: params }} 
    ] 
    }) 
}) 

次に、テストではparams.next(newValue)で新しい値を出力します。

第2に、tick()に電話する必要があります。これはfakeAsyncの仕組みです。非同期タスク解決を制御します。私たちがイベントを送った瞬間に、耳障りなものとして観測可能なので、同期して加入者に届くことはありません。だから我々はここでtick()

に同期動作を強制する必要があり、完全なテスト(Subject'rxjs/Subject'から輸入される)

@Component({ 
    selector: 'test', 
    template: ` 
    ` 
}) 
export class TestComponent implements OnInit { 

    _pageToShow: string; 

    constructor(private _route: ActivatedRoute) { 
    } 

    ngOnInit() { 
    this._route.params.forEach((params: Params) => { 
     if (params['area']) { 
     this._pageToShow = params['area']; 
     } 
    }); 
    } 
} 

describe('TestComponent',() => { 
    let fixture: ComponentFixture<TestComponent>; 
    let component: TestComponent; 
    let params: Subject<Params>; 

    beforeEach(() => { 
    params = new Subject<Params>(); 
    TestBed.configureTestingModule({ 
     declarations: [ TestComponent ], 
     providers: [ 
     { provide: ActivatedRoute, useValue: { params: params } } 
     ] 
    }); 
    fixture = TestBed.createComponent(TestComponent); 
    component = fixture.componentInstance; 
    }); 

    it('should change on route param change', fakeAsync(() => { 
    // this calls ngOnInit and we subscribe 
    fixture.detectChanges(); 

    params.next({ 'area': 'Terry' }); 

    // tick to make sure the async observable resolves 
    tick(); 

    expect(component._pageToShow).toBe('Terry'); 

    params.next({ 'area': 'Billy' }); 
    tick(); 

    expect(component._pageToShow).toBe('Billy'); 
    })); 
}); 
+1

は 'ダニ()'関数に含めるために、この溶液中で、下にスクロールすることを確認しています!私は完全に初めてそれを逃した。ソリューションをありがとう、これは私のために働いた:) –

+0

私は内部リンクの 'フラグメント'のためにこのアプローチを使用することができました: 'fragment = new Subject ();'、タブの内容の隠蔽/表示に適しています、 例えば。 –

関連する問題