question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

TestBed beforeEach docs aren't coherent with CLI Generate

See original GitHub issue

šŸ“š Docs or angular.io bug report

Description

The docs on Calling compileComponents (https://angular.io/guide/testing-components-scenarios#calling-compilecomponents) specify the following :

beforeEach(waitForAsync(() => {
  TestBed
      .configureTestingModule({
        declarations: [BannerComponent],
      })
      .compileComponents()
      .then(() => {
        fixture = TestBed.createComponent(BannerComponent);
        component = fixture.componentInstance;
        h1 = fixture.nativeElement.querySelector('h1');
      });
}));

but the v11 cli generates the following :

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ MyComponent ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

So my question is what is the good practice here ? And if we can just async/await compileComponents why the docs specify to use waitForAsync ?

And in the cli v11 generated file since we’re awaiting compileComponents can’t we merge both beforeEach in the async one ? Like this

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ MyComponent ]
    })
    .compileComponents();

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

šŸŒ Your Environment

Angular CLI: 11.0.1 Node: 12.13.1 OS: win32 x64

Angular: 11.0.0 … animations, common, compiler, compiler-cli, core, forms … platform-browser, platform-browser-dynamic, router Ivy Workspace: Yes

Package Version

@angular-devkit/architect 0.1100.1 @angular-devkit/build-angular 0.1100.1 @angular-devkit/core 11.0.1 @angular-devkit/schematics 11.0.1 @angular/cli 11.0.1 @schematics/angular 11.0.1 @schematics/update 0.1100.1 rxjs 6.6.3 typescript 4.0.5

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
petebacondarwincommented, May 5, 2021

It’s not a dumb question at all! I asked the same recently.

One thing to be aware of is that async-await will literally only wait for the promises that are either awaited or returned from the function before continuing, while waitForAsync() will also wait for the NgZone to ā€œsettleā€, which includes waiting for things like setTimeout(), XHR requests, and other macro tasks to complete.

From the point of view of compileComponents() it returns a Promise that literally only resolves when the compilation is complete, so async-await is enough.

But in your own tests you might like to ensure that your async test does not exit until certain macro tasks have completed. A trivial and artificial example:

it('should wait for all the time-out handlers to complete', waitForAsync(() => {
  let count = 0;
  setTimeout(() => count++, 100);
  setTimeout(() => count++, 100);
  setTimeout(() => count++, 100);
  setTimeout(() => expect(count).toEqual(3), 500);
}));

Without the waitForAsync() the expectation would never be checked.

Of course this example would be much better to do like:

it('should wait for all the time-out handlers to complete', done => {
  let count = 0;
  setTimeout(() => count++, 100);
  setTimeout(() => count++, 100);
  setTimeout(() => count++, 100);
  setTimeout(() => {
    expect(count).toEqual(3);
    done();
  }, 500);
});
1reaction
petebacondarwincommented, May 3, 2021

@iRealNirmal - I think we could update the docs to match the CLI. But @alan-agius4 and I think we could probably also consolidate the two beforeEach blocks in new projects…

Also I just want to check with the FW team that we do actually want to use async () => {...} here rather than waitForAsync(() => { ... }), since they have slightly different semantics

Read more comments on GitHub >

github_iconTop Results From Across the Web

Component testing scenarios - Angular
The TestBed throws an error if you try. Make compileComponents() the last step before calling TestBed.createComponent() . The synchronous beforeEach link. TheĀ ...
Read more >
Angular / Angular guidelines and best practices / Testing
You can test component A using real components B, C, and D and real services S1 and S2. This will make the TestBed...
Read more >
Testing - Angular
Most test suites in this guide call beforeEach() to set the preconditions for each it() test and rely on the TestBed to create...
Read more >
Introduction to Testing Angular Applications | Web Age Solutions
Angular CLI setup should be similar. The details of some of the configuration files above are not provided but can be found in...
Read more >
Angular Testing: A Developer's Introduction - SitePoint
In the second beforeEach() function, we create an instance of the component-under-test . Once we do this we can't configure the TestBed again,Ā ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found