Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot Read Property 'subscribe' of Angular Test Mock

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);
}
like image 359
Dan Forbes Avatar asked May 05 '17 04:05

Dan Forbes


1 Answers

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);
      });
    })));
  });
like image 180
Julia Passynkova Avatar answered Nov 11 '22 21:11

Julia Passynkova