duhovicm
duhovicm

Reputation: 57

Angular Testing With Jasmine "Expected spy to have been called."

Hope you can help me with this thing that has been bugging me for a while.

I am writing some unit tests that accompany a component I wrote, and whatever I do, I can't fix this Expected spy getTopRatedMedia to have been called issue that keeps on appearing.

This test should check whether a service method has been triggered, but it keeps logging "Expected spy getTopRatedMedia to have been called."

media-list-page.component.ts

async onMediaChange(media: string): Promise<void> {
    this.typeOfMedia = media;
    if (!this.searchParam || this.searchParam.length <= 2) {
      this.typeOfMedia = media;

      try {
        this.loader.show();   
        if (!this.configurationString) {
          await this.stateService.getConfiguration();
        }

        let response = await this.api.getTopRatedMedia(media);

        this.mapMedia(response);
        this.loader.hide();
      } catch (err) {
        this.loader.hide();
        console.log(err);
      }
    } else {
      this.onSearchChange(this.searchParam);
    }
  }

media-list-page.component.spec.ts

fdescribe('MediaListPageComponent', () => {
  let component: MediaListPageComponent;
  let fixture: ComponentFixture<MediaListPageComponent>;
  let api: MockedApiService;
  let stateService: MockedStateService;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [RouterModule.forRoot([]), HttpClientTestingModule],
      declarations: [MediaListPageComponent, LoaderComponent],
      providers: [
        { provide: ApiService, useClass: MockedApiService },
        { provide: StateService, useClass: MockedStateService },
      ],
    }).compileComponents();
  });

  beforeEach(async () => {
    fixture = TestBed.createComponent(MediaListPageComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    await component.ngOnInit();
    api = new MockedApiService();
    stateService = new MockedStateService();
    await fixture.whenStable();
  });

  //// FAILING TEST ////
  it('should call the api method getTopRatedMedia()', () => {
    const fixture = TestBed.createComponent(MediaListPageComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    spyOn(api, 'getTopRatedMedia').and.callThrough();
    component.onMediaChange('shows');
    fixture.detectChanges();
    expect(api.getTopRatedMedia).toHaveBeenCalled();
  });

mocks.ts

@Injectable({
  providedIn: 'root',
})
export class MockedApiService {
  getTopRatedMedia() {
    return {
     // returns a mocked object
    };
  }

Thanks for any help :)

Upvotes: 0

Views: 3475

Answers (1)

AliF50
AliF50

Reputation: 18899

Are you sure that the first if is truthy? Meaning it goes inside of the if(!this.searchParam || this.searchParam.length <= 2) ?

If yes, I am thinking you have to wait for the promises to complete before doing the assertions.

//// FAILING TEST ////
  it('should call the api method getTopRatedMedia()', async() => { // add async here
    const fixture = TestBed.createComponent(MediaListPageComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    spyOn(api, 'getTopRatedMedia').and.callThrough();
    component.searchParams = ''; // maybe not needed, but make sure it goes inside of first if
    component.onMediaChange('shows');
    fixture.detectChanges();
    await fixture.whenStable(); // wait for await this.stateService.getConfiguration(); to finish
    await fixture.whenStable(); // wait for await this.api.getTopRatedMedia(media); to finish
    expect(api.getTopRatedMedia).toHaveBeenCalled();
  });

The second await fixture.whenStable() might be optional/not needed, try it with only one.

Upvotes: 1

Related Questions