Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why TestBed beforeeach uses waitForAsync instead of just async/await compileComponents?

EDIT : I opened an issue at Angular and they updated the docs : https://github.com/angular/angular/issues/39740

In Angular tests the usual thing is to do this for the beforeEach method

    beforeEach(waitForAsync(() => {
      TestBed
          .configureTestingModule({
            declarations: [BannerComponent],
          })
          .compileComponents();  // compile template and css
    }));

What's the difference with doing the following ?

    beforeEach(async () => {
      await TestBed
          .configureTestingModule({
              declarations: [BannerComponent],
          })
          .compileComponents();  // compile template and css
    });

I tried to find an explanation in the docs but couldn't figure it out.

https://angular.io/api/core/testing/waitForAsync#description https://v10.angular.io/guide/testing-components-scenarios#the-async-beforeeach

like image 664
Yohan Dahmani Avatar asked Sep 12 '25 13:09

Yohan Dahmani


1 Answers

About the two methods

We have various ways we can define async operations in testing angular operation

  • using waitForAsync()

waitForAsync

Wraps a test function in an asynchronous test zone. The test will automatically complete when all asynchronous calls within this zone are done. Can be used to wrap an inject call. From the doc

It is also important to note that this method is a renaming of the initial method async.

async

Deprecated: use waitForAsync(), (expected removal in v12)

async() helper renamed

The testing helper function async has been deprecated and renamed waitForAsync.

The reason behind this renaming is that it can be confusing to have a function named async() when we now have a JavaScript keyword named async (that keyword did not exist when the Angular function was created), which is slightly similar (you can await asynchronous calls), but different (async() waits for all asynchronous calls, where async only waits for the calls marked with await).

Credit to Cédric Exbrayat See this article

WaitForAsync function executes the code inside its body in a special async test zone. This keeps track of all the promises that are created in the body. The function also tracks any promises created by nested function for example if we call an asynchronous function in in the ngOnInit function, this would be tracked.

  • Using Async/ Await

Basically this uses the normal Javascript async\ await. We declare a function as async and await for a promise to resolve

What is difference between the two approaches?

Let consider a test with 5 methods asyncMethod1,nonAsyncMethod1, asyncMethod2, asyncMethod3, nonAsyncMethod2.

Using async / await. we will need to do below

beforeEach(async () => {
   await asyncMethod1();
   nonAsyncMethod1(); 
   await asyncMethod2();
   await asyncMethod3();
   nonAsyncMethod2()
   await TestBed
      .configureTestingModule({
          declarations: [BannerComponent],
      })
      .compileComponents();  // compile template and css
});

using waitForAsync the above would be

beforeEach(waitForAsync(() => {
   asyncMethod1();
   nonAsyncMethod1(); 
   asyncMethod2();
   asyncMethod3();
   nonAsyncMethod2()
   TestBed
      .configureTestingModule({
        declarations: [BannerComponent],
      })
      .compileComponents();  // compile template and css
}));

So generally when using async /await, we would need to track all our asynchronous operations while using waitForAsync this would be tracked by the function and promise resolved once all promises in the body of the function have been resolved

like image 67
Owen Kelvin Avatar answered Sep 15 '25 06:09

Owen Kelvin