How to mock an activatedRoute parent Route in angular2 for testing purposes?

后端 未结 6 481
渐次进展
渐次进展 2020-12-05 03:57

Let\'s say I have this

export class QuestionnaireQuestionsComponent {

    questions: Question[] = [];
    private loading:boolean = true;


    constructor(         


        
相关标签:
6条回答
  • 2020-12-05 04:34

    For scenarios in which you are reading the query params from the ActivatedRouteSnapshot like:

    this.someProperty = this.route.snapshot.data.query['paramKey'];
    

    The below code will be helpful in tests for feeding query params data into the route

    { 
      provide: ActivatedRoute, 
      useValue: {
        snapshot: {
          data: {
            query: {
              paramKey: 'paramValue'
            }
          }
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-05 04:35

    Using TestBed

     beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [YourComponent],
          imports: [],
          providers: [
            {
              provide: ActivatedRoute, useValue: {
                params: Observable.of({ id: 'test' })
              }
            }
          ]
        })
          .compileComponents();
      }));

    0 讨论(0)
  • 2020-12-05 04:46

    AcitvatedRoute is an interface according to angular2 docs, so what I did is implements a MockActivatedRoute

    import {Observable} from 'rxjs';
    import {Type} from '@angular/core';
    import {ActivatedRoute,Route,ActivatedRouteSnapshot,UrlSegment,Params,Data } from '@angular/router';
    
    export class MockActivatedRoute implements ActivatedRoute{
        snapshot : ActivatedRouteSnapshot;
        url : Observable<UrlSegment[]>;
        params : Observable<Params>;
        queryParams : Observable<Params>;
        fragment : Observable<string>;
        data : Observable<Data>;
        outlet : string;
        component : Type<any>|string;
        routeConfig : Route;
        root : ActivatedRoute;
        parent : ActivatedRoute;
        firstChild : ActivatedRoute;
        children : ActivatedRoute[];
        pathFromRoot : ActivatedRoute[];
        toString() : string{
            return "";
        };
    }
    

    and just replace the ActivatedRoute in my tests for MockActivatedRoute like this

    beforeEach(()=>{
        route = new MockActivatedRoute();
        route.parent = new MockActivatedRoute();
        route.parent.params = Observable.of({id:"testId"});
    
        questionnaireService = jasmine.createSpyObj('QuestionnaireService', ['getQuestionsForQuestionnaire']);
        questionnaireService.getQuestionsForQuestionnaire.and.callFake(() => Observable.of(undefined));
        component = new QuestionnaireQuestionsComponent(route, questionnaireService);
    });
    
    0 讨论(0)
  • 2020-12-05 04:56

    You can also simple plass {params: {searchTerm: 'this is not me'}} as any) as ActivatedRouteSnapshot

    detailds code

      (service.resolve(({params: {id: 'this is id'}} as any) as ActivatedRouteSnapshot,
        {} as RouterStateSnapshot)as Observable<xyzResolveData>)
        .subscribe((data) => {
          expect((data as xyzResolveData).results).toEqual(xyzData.results);
        });
    
    0 讨论(0)
  • 2020-12-05 04:58

    For anyone new to this question the angular.io docs cover this scenario. See here

    As per documentation above:

    Create ActivatedRouteStub class to be used as test double for ActivatedRoute

    import { ReplaySubject } from 'rxjs/ReplaySubject';
    import { convertToParamMap, ParamMap, Params } from '@angular/router';
    
    /**
     * An ActivateRoute test double with a `paramMap` observable.
     * Use the `setParamMap()` method to add the next `paramMap` value.
     */
    export class ActivatedRouteStub {
      // Use a ReplaySubject to share previous values with subscribers
      // and pump new values into the `paramMap` observable
      private subject = new ReplaySubject<ParamMap>();
    
      constructor(initialParams?: Params) {
        this.setParamMap(initialParams);
      }
    
      /** The mock paramMap observable */
      readonly paramMap = this.subject.asObservable();
    
      /** Set the paramMap observables's next value */
      setParamMap(params?: Params) {
        this.subject.next(convertToParamMap(params));
      };
    }
    

    And then use the stub in the test class as follows:

    activatedRoute.setParamMap({ id: '1234' });
    
    0 讨论(0)
  • 2020-12-05 05:01

    To customize a mocked ActivatedRoute's data inside each 'it' block, combine what Kevin Black suggested above

    beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [YourComponent],
          imports: [],
          providers: [
            {
              provide: ActivatedRoute, useValue: {
                queryParams: of({ id: 'test' })
              }
            }
          ]
        })
          .compileComponents();
      }));

    and the below code in the it('') block before instantiating a component using fixture.detectChanges()

    it('test', fakeAsync(() => {
      let activatedRoute: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
      activatedRoute.queryParams = of({ firstName: 'john', lastName: 'smith' });
    
      fixture.detectChanges(); // trigger ngOninit()
      tick();
    }));

    0 讨论(0)
提交回复
热议问题