Angular Karma-Jasmine - Spec is not waiting for .then blocks to finish before running expect?

17 Views Asked by At

I have a service in Angular that runs a function in order to fetch data from some internal API endpoints. The structure of this function is as follows (with console logs for clarity on execution order):

  async initializeAPI() {
    let data = await fetch('//my 1st api call');
    data.json().then(r => {
      console.log("then1");
      this.CLASSDATA = r.res.rows;
    });
    console.log("API read_classdata called");

    data = await fetch('//my 2nd api call');
    data.json().then(r => {
      console.log("then2");
      this.RABILITYDATA = r.res.rows;      
    });

    data = await fetch('//my 3rd api call');
    data.json().then(r => {
      this.PABILITYDATA = r.res.rows;   
      console.log("then3", r.res.rows[0], this.PABILITYDATA[0]);
    });
    console.log("API read_abilitydata called");
  }

I am now trying to test this function in my spec.ts file, to confirm that all the data is fetched and parsed properly. However, I have not found an approach that allows all of these .then blocks to finish before starting in on expect statements.

In my spec, I set up some mockdata and pass those to a fetch spy to handle the fetches. As far as I can tell, that part is working fine. My spec.ts looks as follows:

setup and beforeEach-

  let service: PartyService;  
  let initspy: jasmine.Spy;

  //also the mockdata is set up here, left out for legibility

  beforeEach(() => {
    //this prevents initializeAPI in constructor from running and making real fetch calls
    initspy = spyOn(PartyService.prototype, "initializeAPI"); 

    TestBed.configureTestingModule({});
    service = TestBed.inject(PartyService);
  }

test case-


  it('should initialize apis for class and ability', async() => {
    service.CLASSDATA = [];
    const fetchspy = spyOn(window, 'fetch').and.returnValues(Promise.resolve(classres), Promise.resolve(rabres), Promise.resolve(pabres) ); //returning mockdata for all 3 fetches using spy
    initspy = initspy.and.callThrough();
    await service.initializeAPI();

    expect(fetchspy).toHaveBeenCalledTimes(3); //this passes
    expect(service.CLASSDATA).toEqual(MOCKCLASSDATA); //this is failing
  });

However, my console prints the logs in the following order:

API read_classdata called
API read_abilitydata called
spec checkpoint
[TEST FAILS HERE]
then1 through then3 here, with data assigned correctly

Based on these console logs, it seems to me that the test case successfully waits for the fake fetch() requests to finish, but does NOT wait for the .then blocks that process the fetched data.

I've tried a few variants, including using fakeAsync() with tick(), waitForAsync, and making a spy for Response.then(), but either I've missed a trick while implementing these approaches or else they don't fix the underlying issue.

Could this be a problem with the implementation of my original service function that I need to change? Is there a way to rewrite the test case such that it does wait for the .then blocks? Thank you in advance for your time!

0

There are 0 best solutions below