Подписаться на активированный параметр маршрута в модульном тесте Angular9 - PullRequest
2 голосов
/ 06 апреля 2020

У меня проблема с модульным тестированием следующего компонента Angular 9:

export class BirdsDetailComponent implements OnInit {
  ...

  constructor(private service: BirdsService
    , private flickr: FlickrService
    , private route: ActivatedRoute
    , private location: Location
    , private router: Router) {
    route.params.subscribe(_ => {
      this.route.paramMap.subscribe(pmap => this.getData(+pmap.get('id')));
    });
  }

  ngOnInit() {}

  getData(id: number): void { ... }

В отличие от других знакомых мне компонентов, этот компонент инициирует извлечение данных из конструктора.

У меня проблема (я думаю) с настройкой параметра маршрута. Я пробовал ряд способов настройки активированного маршрута макета / заглушки. Включая тот, который находится в этой настройке в Angular документах .

describe('BirdsDetailComponent', () => {

  let component: BirdsDetailComponent;
  let fixture: ComponentFixture<BirdsDetailComponent>;

  let activatedRoute: ActivatedRouteStub;

  beforeEach(() => {
    activatedRoute = new ActivatedRouteStub();
  });

  let mockBirdsService;
  let mockFlickrService;

  // the `id` value is irrelevant because ignored by service stub
  beforeEach(() => activatedRoute.setParamMap({ id: 99999 }));

  beforeEach(async(() => {
    const routerSpy = createRouterSpy();
    function createRouterSpy() {
      return jasmine.createSpyObj('Router', ['navigate']);
    }
    mockBirdsService = jasmine.createSpyObj(['getData']);

    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes([])],
      declarations: [BirdsDetailComponent],
      providers: [
        { provide: BirdsService, useValue: mockBirdsService },
        { provide: FlickrService, useValue: mockFlickrService },
        { provide: Router, useValue: routerSpy },
        {
          provide: ActivatedRoute, useValue: ActivatedRouteStub
        }
        // {
        //   provide: ActivatedRoute,
        //   useValue: {
        //     params: of({ id: '123' })
        //   }
        // }
      ]
    })
      .compileComponents();
  }));


  beforeEach(() => {
    fixture = TestBed.createComponent(BirdsDetailComponent);
    component = fixture.componentInstance;

    activatedRoute.setParamMap({ id: 1 });
  });

  it('should call getData', () => {
    const conserveStatus = {
      conservationStatusId: 1, conservationList: 'string',
      conservationListColourCode: 'string', description: 'string', creationDate: 'Date | string',
      lastUpdateDate: 'Date | string', birds: []
    };

    const bird = {
      birdId: 1, class: 'string', order: 'string', family: 'string',
      genus: 'string', species: 'string', englishName: 'string', populationSize: 'string',
      btoStatusInBritain: 'string', thumbnailUrl: 'string', songUrl: 'string',
      birderStatus: 'string', birdConservationStatus: conserveStatus,
      internationalName: 'string', category: 'string', creationDate: 'Date | string',
      lastUpdateDate: 'Date | string'
    };

    mockBirdsService.getData.and.returnValue(of(bird));

    fixture.detectChanges();
    // // Act or change
    // component.getBird(1);

    // // fixture.detectChanges();

    // Assert
    expect(mockBirdsService.getBird).toHaveBeenCalled();
  });

});

Я также попробовал простую настройку активированного параметра маршрута, который вы можете увидеть в закомментированном код, подобный этому (и его разновидности):

 {
   provide: ActivatedRoute,
   useValue: {
     params: of({ id: '123' })
   }
 }

Что бы я ни пытался, мне кажется, что я столкнулся с ошибкой "Cannot read property" subscribe "undefined брошено". Может ли проблема быть связана с обнаружением изменений? Кто-нибудь может указать мне правильное направление?

...