Thursday, April 19, 2018

Testing Angular 5 Promises and Tick

I have a function that calls two other functions that return promises. Each promise has a callback (.then) chained to it, which will also return another promise (because that's how promises work). Once both promises are resolved and their callbacks are complete, I take one final action. It looks like this:
   1:  const promises: Promise<void>[] = [];
   2:  promises.push(this.service.doTheFirstThingThatReturnsAPromise().then(result => {
   3:    this.firstProp = true;
   4:  }));
   5:
   6:  promises.push(this.service.doTheSecondThingThatReturnsAPromise().then(result => {
   7:    this.secondProp = true;
   8:  }));
   9:
  10:  Promise.all(promises).then(() => {
  11:    this.thirdProp = true;
  12:  });

My problem arose when I tried to test this. It seemed like everything should have been working fine with this test:
   1:  beforeEach(() =>{
   2:    component.doTheThingThatDoesTheOtherThings();
   3:  });
   4:
   5:  it('should do some stuff', fakeAsync(()=>{
   6:    tick();
   7:    expect(component.firstProp).toBe(true);
   8:    expect(component.secondProp).toBe(true);
   9:    expect(component.thirdProp).toBe(true);
  10:  }));

I've done almost exactly this before (in this same project no less!) and it worked fine. The only difference was that in this case I decided to move my target function invocation inside my beforeEach and that made all the difference. With the function invocation happening inside the beforeEach, my entire test was completing before the tick was ever process (which I still don't fully understand, which is part of the reason I'm writing this up). All I had to do to get my tests to pass was move the target function invocation into my spec instead of the beforeEach. So my final (working) result looks like this:
   1:  it('should do some stuff', fakeAsync(()=>{
   2:    component.doTheThingThatDoesTheOtherThings();
   3:    tick();
   4:    expect(component.firstProp).toBe(true);
   5:    expect(component.secondProp).toBe(true);
   6:    expect(component.thirdProp).toBe(true);
   7:  }));

Fortunately, that only took me about 30 minutes to figure out. Hopefully next time I encounter something similar I check back here first and save myself that 30 minutes.

No comments:

Post a Comment