javascript - Angular 9 testing komponent avhengig av tjeneste med observable - Kan ikke lese egenskapen 'subscribe' av undefined


Jeg prøver desperat å teste en komponent som bruker en tjeneste. Jeg bruker spy for å mocke den, men hver gang jeg kjører tester feiler det med en unntak:

Kan ikke lese egenskapen 'subscribe' av undefined

Min test ser slik ut:

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

  let filmsServiceSpy: jasmine.SpyObj<FilmsService>;

  beforeEach(async(() => {
    const spy = jasmine.createSpyObj('FilmsService', 
    ['searchFilmByID']
    );

    TestBed.configureTestingModule({
      declarations: [ FilmOverviewComponent ],
      providers: [
        {provide: AppTitleService, useValue: {getTitle: () => 'title'}},
        {provide: ActivatedRoute, useValue: {params: of({id: 123})} },
        {provide: FilmsService, useValue: spy}
      ]
    })
    .compileComponents();

    filmsServiceSpy = TestBed.get(FilmsService);
  }));

  beforeEach(() => {
    filmsServiceSpy.searchFilmByID.and.returnValue(Observable.create([{title: "", year: ""}]));
    fixture = TestBed.createComponent(FilmOverviewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

Metoder som brukes i tjenesten:

searchFilmByID(movieID: string): Observable<Film> {
    return this.http.get<Film>(this.getUrlWithID(movieID));
  }

  private getUrlWithID(movieID: string) {
    return 'api/externalfilms/film/' + movieID;
  }

Jeg har ingen idé om hvordan jeg skal takle dette. Jeg mistenker at det ville bli løst med en slags mocking av subscribe-metoden, men jeg feilet fullstendig med det.

Takk for hjelpen på forhånd!

Svar #1

Feilen kommer fra this.http.get<Film>.... Det finnes 2 måter å løse det på.

Første måte - latterliggjøre HTTP-klienttjeneste og kalle på falsk

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

  let filmsService: FilmsService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FilmOverviewComponent ],
      imports: [ HttpClientTestingModule ],
      providers: [
        {provide: AppTitleService, useValue: {getTitle: () => 'title'}},
        {provide: ActivatedRoute, useValue: {params: of({id: 123})} },
        FilmsService
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    filmsService = TestBed.inject(FilmsService);

    /* Mock response */
    const httpClient: HttpClient = TestBed.inject(HttpClient);
    spyOn(httpClient, 'get').and.callFake(() => of({title: "", year: ""}));

    fixture = TestBed.createComponent(FilmOverviewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

Andre måte - kall falsk servicemetode

const FilmsServiceStub = jasmine.createSpyObj('FilmsService', ['searchFilmByID']);

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

  let filmsService: FilmsService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FilmOverviewComponent ],
      providers: [
        {provide: AppTitleService, useValue: {getTitle: () => 'title'}},
        {provide: ActivatedRoute, useValue: {params: of({id: 123})} },
        {provide: FilmsService, useValue: FilmsServiceStub}
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    filmsService = TestBed.inject(FilmsService);

    /* Mock response */
    spyOn(filmsService, 'searchFilmByID').and.callFake(() => of({title: "", year: ""}));

    fixture = TestBed.createComponent(FilmOverviewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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