Как я могу получить экземпляр не тестируемого компонента внутри моего тестового примера

У меня есть компонент ValidateSessionComponentwhich uses another component 'LoginFormComponent'. 'LoginFormComponent' emits a value whichValidateSessionComponentshould get should then callsigninmeethod of theUserManagementService. Я написал следующий тестовый пример, но получаю сообщение об ошибке «Ошибка: StaticInjectorError [LoginFormComponent]: NullInjectorError: Нет поставщика для LoginFormComponent!»

Почему появляется эта ошибка и как ее исправить.

describe('ValidateSessionComponent tests with route parameters', () => {
  let component: ValidateSessionComponent;
  let fixture: ComponentFixture<ValidateSessionComponent>;

  beforeEach(async()=>{
    TestBed.configureTestingModule({
      declarations: [ LoginFormComponent, //I AM INJECTING THE LOGINFORMCOMPONENT HERE
        NavComponentComponent,
        ContentComponentComponent,
        FooterComponentComponent,
        HomepageContentComponentComponent,
        ShowErrorsComponent,
        ProgressBarComponent,
        SignupComponentComponent,
        HomepageContentComponentComponent,
        NewPracticeQuestionComponent,
        PraticeQuestionListComponent,
        QuestionDetailsComponent,
        PageNotFoundComponent,
        DialogBoxComponent,
        ValidateSessionComponent],
      imports:[ReactiveFormsModule,
        RouterModule,
        HttpClientModule,
        AppRoutingModule
      ],
      providers:[
        {provide: UserManagementService, useClass: MockUserManagementService},//mock user management service
        HelperService,
        DialogBoxService,
        {provide: APP_BASE_HREF, useValue: '/'}
      ]
    })
      .compileComponents();
  });


  beforeEach(() => {
    fixture = TestBed.createComponent(ValidateSessionComponent);
    component = fixture.componentInstance;
    //using component['activatedRoute'] instead of component.route to remove editor's error that route is private.
    /*
    this is the way to return different values from a spy based on the received argument. The route will have
    params like
    {
      username:..
      redirect-to:...
      additional-redirect-info:..
    }
     */
    spyOn(component['activatedRoute'].snapshot.paramMap,'get').and.callFake(function() {
     let param = arguments[0];
     console.log('param in fake function ',param);
     if(param==='username'){
       return '[email protected]'
     }
      if(param==='redirect-to'){
        return '/home'
      }
      if(param==='additional-redirect-info'){
        return {somearg:'somevalue'}
      }
      console.log('returning unknown param',param);
     return param;
    });
    fixture.detectChanges();
  });

  fit('should send signin request on receiving form values ',(done)=>{
    let loginComponent:LoginFormComponent = TestBed.get(LoginFormComponent);
    let userService:UserManagementService = TestBed.get(UserManagementService);
    loginComponent.formOutputEvent.emit(new LoginFormValues('[email protected]','somepassword'));
    spyOn(userService,'signinUser');
    setTimeout(()=>{
      expect(userService.signinUser).toHaveBeenCalledWith(new UserSigninInfo('[email protected]','somepassword'));
      done();
    },1000);

  });
});

В spec, если я удалю LoginFormComponent (чей селектор app-login-form), я получаю сообщение об ошибке «Невозможно привязать к 'userId', поскольку это не известное свойство 'app-login-form'.


person Manu Chadha    schedule 06.10.2019    source источник
comment
вы пробовали импортировать туда RouterTestingModule?   -  person Amir Christian    schedule 06.10.2019
comment
А модуль в котором определяется LoginFormComponent?   -  person Amir Christian    schedule 06.10.2019
comment
пробовал, но ничего не получилось.   -  person Manu Chadha    schedule 06.10.2019


Ответы (1)


Чтобы получить ссылку на компонент, я использовал Viewchild. ссылка из ViewChild - Как получить ссылку на дочерний компонент и передать значение из дочернего компонента

Что касается проблемы, с которой я столкнулся, похоже, проблема заключалась в многократном включении LoginFormComponent. HTML-код ValidateSessionComponent содержал ссылку на LoginFormComponent.

<app-login-form (formOutputEvent)="handleFormValues($event)" [userId]="username"></app-login-form>

Пока это работает нормально. Затем я решил также включить ссылку на проход LoginFormComponent через DI в ValidateSessionComponent

constructor(private loginForm2:LoginFormComponent,private helper:HelperService,private dialogService:DialogBoxService,private activatedRoute:ActivatedRoute, private router:Router, private userManagementService:UserManagementService) { }

Это начало вызывать ошибку StaticInjectorError(DynamicTestModule)[ValidateSessionComponent -> LoginFormComponent]: StaticInjectorError(Platform: core)[ValidateSessionComponent -> LoginFormComponent]: NullInjectorError: No provider for LoginFormComponent!

Честно говоря, я не могу понять причину, то есть что происходит под капотом в Angular, что вызывает эту проблему.

person Manu Chadha    schedule 07.10.2019
comment
этот ответ содержит более подробную информацию - stackoverflow.com/questions/58265549/ - person Manu Chadha; 07.10.2019