9

경로 매개 변수의 변경에 응답하는 각도 2의 구성 요소가 있습니다 (주 라우트에서 벗어나지 않기 때문에 구성 요소가 처음부터 다시로드되지 않습니다. 구성 요소 코드 :. 이것은 치료와 _pageToShow 작동각도 2 - 경로 매개 변수의 변경에 대한 테스트

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

내가 경로의 변경 (관찰의 때문에 두 번째 트리거의 동작을 테스트하기 위해 노력하고있어 탐색에 적절한 설정되어 있지만 그건 나를 위해 일하는 것을 거부했습니다.) 내 시도는 다음과 같습니다.

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(); 행없이 실행하면 두 번째 기대가 실패하여 실패합니다.

답변

14

먼저 Observable 대신 Subject을 사용해야합니다. 관측 대상은 한 번만 구독합니다. 따라서 첫 번째 매개 변수 세트 만 방출합니다. Subject을 사용하면 항목을 계속 내보내고 단일 구독으로 계속 항목을 가져올 수 있습니다.

let params: Subject<Params>; 

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

그런 다음 테스트에서 단지 params.next(newValue) 새로운 값을 방출한다.

두 번째로 tick()으로 전화해야합니다. 이것이 fakeAsync의 작동 방식입니다. 비동기 태스크 분석을 제어합니다. 우리가 이벤트를 보냈을 때 asychrounous처럼 관측 가능하기 때문에, 가입자에게 동 기적으로 도달하지 못합니다. 그래서 우리는()은`틱에 포함이 솔루션에서 아래로 스크롤해야합니다 완전한 테스트 (Subject'rxjs/Subject'에서 수입되는) 여기 tick()

@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'에도이 방법을 사용할 수있었습니다 :'fragment = new Subject ();', 탭 내용 숨기기/표시에 적합합니다. 예를 들면. –

관련 문제