2

I'm struggling with testing an Angular2 component that has a service injected. The test code is below but basically:

• SearchComponent takes a FightService in the constrctor.

• The constructor calls a flightsService.getFlights() which fires off an HTTP request. flightsService.getFlights() returns an observable.

• The constructor subscribes to the observable returned which populates the allSummaryItems array.

My MockFlightService isn't being used, it basically fails saying there is no provider for Http (which is in the FlightService constructor). If I add HttpModule to the providers in TestBed, then it goes off and fires the real Http request.

How can I make sure I'm using MockFlightService? Also will this test the observable properly, even when firing a real Http request I can see that the subscribed methods aren't being called?

Thanks

class MockFlightsService {
  public getFlights = () => {
    return new Observable<any>(() => { return dummyData.json(); });
  };
}

describe('SearchComponent Tests', () => {
  let fixture: ComponentFixture<SearchComponent>;
  let component: SearchComponent;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [SearchComponent],
      imports: [RouterModule],
      providers: [{ provide: FlightsService, useClass: MockFlightsService }]
    });

    fixture = TestBed.createComponent(SearchComponent);
    fixture.detectChanges();
  });

  it('should render list', fakeAsync(() => {
    fixture.whenStable();
    component = fixture.componentInstance;
    console.log(component.allSummaryItems); // this is empty, shouldn't be
  }));
});

I'm using Angular 2.0.1.

C.Champagne
  • 5,381
  • 2
  • 23
  • 35
big_tommy_7bb
  • 1,257
  • 2
  • 21
  • 37

1 Answers1

2

My MockFlightService isn't being used, it basically fails saying there is no provider for Http (which is in the FlightService constructor)

With the configuration you are showing, the only way I can see this happening, is if you listed the service in the @Component.providers. This will override any module level providers. I was tearing my hair out for a whole day because I completely forgot that I had it there.

If the service is supposed to be an application wide provider, then take it out of the @Component.providers and add it to the @NgModule.providers.

If your goal is to restrict the service to the component level, then what you should do instead is override the providers in the test component, instead of adding the provider into the test module.

TestBed.overrideComponent(SearchComponent, {
  set: {
    providers: [
      { provide: FlightsService, useClass: MockFlightsService }
    ]
  }
});

This should be done before you create the component.

You can see more here in Overriding Test Providers.

Other things not related the the error.

  • Your use of RouterModule. For testing you should use RouterTestingModule, as mentioned here
  • whenStable returns a promise. Just calling it, doesn't protect you. You need to subscribe to it, then do your stuff there.

    whenStable().then(() => {
      // Do stuff here. This is when the async tasks are completed.
    })
    
  • Check out this post, for an example of how to mock Http, if you ever need to, so that you aren't making an XHR request during a test.

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720