Search code examples
angularunit-testingsubscription

Angular unit test Suscription


I have an angular component that subscribes to a service that sends a boolean. If the value is true, it is supposed to be called a private method. My problem is that I can’t test the call of my private method. It’s not called

private createUser(){
this.submitForm = false;

this.userForm.markAllAsTouched();
if(this.userForm.invalid){
  this.submitForm = true;
  this.formulaireService.setValidForm(false);
  this.formulaireService.setDisableButton(false);
  return;
}


let user = {
  name:  this.userForm.controls['name'].value,
  age:  this.userForm.controls['age'].value
}
}

My Subscription in ngOnInit :

this.subscriptionInitForm = 
    this.formulaireService.sendInitForm$.subscribe((val) => {
      if(val){
        this.createUser();
      }
    });

My unit test :

  it('form is valid', fakeAsync(()=> {
    component.userForm.get('name')?.setValue('NAME');
    component.userForm.get('age')?.setValue('45');

    let service = fixture.debugElement.injector.get(UserService);
    service.setSendInitForm(true);
    tick(500);

    service.sendInitForm$.subscribe((res) => {
      expect(component.user.name).toEqual('NAME ');
    });  

    flush();    
    })

How to do in my test so that once I have init the form, make sure to simulate a value reception of my service so that it calls my private method


Solution

  • I would mock the formulaireService. The first fixture.detectChanges() is when ngOnInit is called.

    let component: ...;
    let mockFormulaireService: jasmine.SpyObj<FormulaireService>;
    const mockSendInitForm = new BehaviorSubject<boolean>(true);
    
    beforeEach(waitForAsync(() => { // can be async await too
      // Mock instance variables in the third argument and assign it to the behavior subject
      mockFormulaireService = jasmine.createSpyObj<FormulaireService>('FormulaireService', {}, 
    { sendInitForm$: mockSendInitForm.asObservable() });
    
       TestBed.configureTestingModule({
         ....
         // !! Provide the fake for the real
         providers: [{
           provide: FormulaireService,
           useValue: mockFormulaireService 
         }]
       }).compileComponents();
    }));
    

    Now if you want sendInitForm to be false, you can do mockSendInitForm.next(false); and the observable stream in the ngOnInit should update.

    Here is how to test components depending on services: https://testing-angular.com/testing-components-depending-on-services/