Cannot Read Property 'subscribe' of Angular Test Mock

13,678

Use inject to inject the service and mock it not stub

it('should create', inject([MyService], (myService: MyService) => {
  spyOn(myService, 'getObservable').and.returnValue({subscribe: () => {}});
  expect(component).toBeTruthy();
}));

Here is full version:

component:

@Component({
  selector: 'my-cmp',
  template: 'my cmp {{x}}'
})
export class MyComponent {
  x;

  constructor(private myService: MyService) {
    this.myService.getObservable()
      .subscribe(x => {
        console.log(x);
        this.x = x;
      });
  }
}

test:

   describe('my component test', () => {
    let fixture: ComponentFixture<MyComponent>, comp: MyComponent, debugElement: DebugElement, element: HTMLElement;

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [MyComponent],
        providers: [MyService]
      });
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(MyComponent);
      comp = fixture.componentInstance;
      debugElement = fixture.debugElement;
      element = debugElement.nativeElement;
    });

    it('should create', inject([MyService], (myService: MyService) => {
      expect(comp).toBeTruthy();
    }));

    it('should set value', async(inject([MyService], (myService: MyService) => {
      spyOn(myService, 'getObservable').and.returnValue(Observable.of(1));

      fixture.detectChanges();

      fixture.whenStable().then(() => {
        expect(comp.x).toEqual(1);
      });
    })));
  });
Share:
13,678

Related videos on Youtube

Dan Forbes
Author by

Dan Forbes

Former wine industry professional and graduate of the University of Texas at Austin with a Bachelor of Science degree in Computer Science.

Updated on June 04, 2022

Comments

  • Dan Forbes
    Dan Forbes almost 2 years

    I'm trying to unit test an Angular component that has an injected service. In the component's constructor, a method on the injected service is called that returns an Observable. I'm trying to mock the service in my component's unit test, but I keep running into this error: TypeError: Cannot read property 'subscribe' of undefined.

    I've tried to mock the service in the following ways:

    const serviceStub = {
      getObservable: () => { return {subscribe: () => {}}; },
    };
    
    beforeEach(async(() => {
      TestBed.configureTestingModule({
        providers: [
          {provide: MyService, useValue: serviceStub}
        ]
    })
    
    
    it('should create', () => {
      spyOn(serviceStub, 'getObservable').and.returnValue({subscribe: () => {}});
      expect(component).toBeTruthy();
    });
    

    It feels like I'm missing something obvious. Can someone please point it out?

    UPDATE

    I get this error even when I inject the actual service in my test bed providers.

    The component's constructor looks something like this:

    private _subscription: Subscription;
    
    constructor(private _service: MyService) {
      this._subscription = _service.getObservable().subscribe(console.log);
    }
    
  • Dan Forbes
    Dan Forbes almost 7 years
    Thank you for your reply, Julia! I look forward to trying this out as soon as I get home!
  • Julia Passynkova
    Julia Passynkova almost 7 years
    welcome. let me know. i have a lot of test similar to that
  • Julia Passynkova
    Julia Passynkova almost 7 years
    i updated the answer. it works for me. please try again.
  • Dan Forbes
    Dan Forbes almost 7 years
    I appreciate your follow-up, but unfortunately, it's still failing with the same error. I looked at the output a little harder, and it appears that the error is coming from the call to TestBed.createComponent, which makes the fact that your suggestions aren't helping make a little more sense, at least...