3

I have this code:

export class ProgramComponent implements OnInit {
   @Input() events: Observable<any>;
   eventsSubscription: any;
   ...
   ngOnInit() {
      this.eventsSubscription = this.events.subscribe((event) => {
          ... <- Some code that I want to test!!!!
          console.log("The test doesn't get past here!!!!");
      });
   }
}

describe('BLA BLA BLA', () => {
   let component: ProgramComponent;
   let fixture: ComponentFixture<ProgramComponent>;

   beforeEach(async(() => {
       TestBed.configureTestingModule({
          imports: [
              ...
          ],
          declarations: [ProgramComponent],
          providers: [
              ...
          ]
       }).compileComponents();
    }));

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

       // HERE I WANT TO SPY ON THAT EVENTS OBSERVABLE AND RETURN SOME VALUE
       // I tried this without success
       spyOn(component, 'events').and.returnValue({type: 'somevalue'}))

       fixture.detectChanges();
    });

    it('should create', () => {
       expect(component).toBeTruthy();
    });
});

The problem is that fixture.detectChanges(); does not trigger the subscribe of the events observable. Do I have to use spyOnProperty? But it's an Input of the component...

I already check this and this.

Thanks!

ismaestro
  • 7,561
  • 8
  • 37
  • 50

1 Answers1

5

Yes, you would have to use spyOnProperty as it is a property you are trying to spy on. But even if it were not a property, your spy is not returning the expected type for it to work. The return value of your spy is just an ordinary object { type: 'somevalue' }, but the events property expects a value of type Observable<any>. This will most likely result in an error as the component tries to call subscribe on the events property, but the ordinary object doesn't provided that method.

For this test case I would just simply provide a mock Observable and test whether the value it emitted was successfully received in your component (I assume you are assigning whatever your are receiving from the Observable to some property in the component).

This could look something like this:

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

it('should test the component', () => {
  // provide an Observable with whatever value you need in your component    
  component.events = of({type: 'somevalue'});

  // nothing happened yet
  expect(component.eventsSubscription).toBeFalsy();
  expect(component.valueReceived).toBeUndefined();

  // this should trigger change detection and your ngOnInit
  fixture.detectChanges();

  // verify whatever you need
  expect(component.eventsSubscription).toBeTruthy();
  expect(component.valueReceived).toEqual({type: 'somevalue'});
});

And in your component:

@Input() events: Observable<any>;
eventsSubscription: any;
valueReceived: any;

ngOnInit() {
  this.eventsSubscription = this.events.subscribe((event) => {
    this.valueReceived = event;
    console.log("The test doesn't get past here!!!!");
  });
}
Fabian Küng
  • 5,925
  • 28
  • 40