Repository navigation
NG 21 + Vitest + Non-stadanlone component with async pipe #65665
Copy link
Copy link
Open
Labels
area: docsRelated to the documentationRelated to the documentationarea: testingIssues related to Angular testing features, such as TestBedIssues related to Angular testing features, such as TestBed
Milestone
Description
Which @angular/* package(s) are the source of the bug?
common
Is this a regression?
Yes
Description
With Angular 21, I can't test (with vitest) a non-standalone component using the Async pipe. I get the following error:
X [ERROR] NG8004: No pipe found with name 'async'.
To fix this, import the "AsyncPipe" class from "@angular/common" and add it to the "imports" array of the module declaring the component. [plugin angular-compiler]
src/app/async-test/async-test.html:1:9:
1 │ <p>{{v | async }}</p>
╵ ~~~~~
Error occurs in the template of component AsyncTestComponent.
src/app/async-test/async-test.ts:6:15:
6 │ templateUrl: './async-test.html',
╵ ~~~~~~~~~~~~~~~~~~~
Here is the full code:
Test
describe('AsyncTestComponent', () => {
let component: AsyncTestComponent;
let fixture: ComponentFixture<AsyncTestComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CommonModule, AsyncPipe ],
declarations: [AsyncTestComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AsyncTestComponent);
component = fixture.componentInstance;
await fixture.whenStable();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Component:
@Component({
selector: 'app-async-test',
templateUrl: './async-test.html',
styleUrl: './async-test.css',
standalone: false
})
export class AsyncTestComponent {
protected readonly v = of(1);
}
HTML:
<p>{{v | async }}</p>
Please provide a link to a minimal reproduction of the bug
ng new --> add a non standalone component and use the async pipe in it then run ng test
Please provide the exception or error you saw
I should be able to test my non-stadanlone component (using AsyncPipe) in angular 21.
Please provide the environment you discovered this bug in (run ng version)
Angular CLI : 21.0.0
Angular : 21.0.0
Node.js : 22.16.0
Package Manager : npm 10.9.2
Operating System : win32 x64
┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/build │ 21.0.0 │ ^21.0.0 │
│ @angular/cli │ 21.0.0 │ ^21.0.0 │
│ @angular/common │ 21.0.0 │ ^21.0.0 │
│ @angular/compiler │ 21.0.0 │ ^21.0.0 │
│ @angular/compiler-cli │ 21.0.0 │ ^21.0.0 │
│ @angular/core │ 21.0.0 │ ^21.0.0 │
│ @angular/forms │ 21.0.0 │ ^21.0.0 │
│ @angular/platform-browser │ 21.0.0 │ ^21.0.0 │
│ @angular/router │ 21.0.0 │ ^21.0.0 │
│ rxjs │ 7.8.2 │ ~7.8.0 │
│ typescript │ 5.9.3 │ ~5.9.2 │
│ vitest │ 4.0.13 │ ^4.0.8 │
└───────────────────────────┴───────────────────┴───────────────────
Anything else?
No response
Reacted by ZeroTermi, paq1, Davz83, Geoffrey Crofte, Matthieu D., Charles-ris, F3YoD, AjayGhales, Christoph Meier, Rokas Brazdžionis and 7 more
Metadata
Metadata
Assignees
Labels
area: docsRelated to the documentationRelated to the documentationarea: testingIssues related to Angular testing features, such as TestBedIssues related to Angular testing features, such as TestBed
Activity
JoostK commentedon Nov 26, 2025
This seems to be working as expected, although an exact reproduction is missing so I do not have the full picture here.
To run tests, the application is built like it normally would. As such, the
AsyncTestComponentcomponent is AOT compiled and the compiler rightfully concludes that theasyncpipe usage is broken, since no correspondingNgModulewould be available that importsAsyncPipeorCommonModule.Scipionh commentedon Nov 26, 2025
Here is a project where the problem occurs:
https://stackblitz.com/edit/hefgnomh
If I run
ng serve(orng build) there is no issue, and the application has the desired behavior.however if I run
ng testHow can I make my test pass here ?
JoostK commentedon Nov 26, 2025
That repro reveals a classic pitfall of NgModules. In a non-test build the
main.tsfile is used as entry-point which importsapp.module.ts, making the compiler aware ofAppModuleand its contribution toAppComponent. In the test build, however, neithermain.tsnorapp.module.tsis part of the compilation, as it's not imported from anywhere nor is it present intsconfig.spec.ts#include.Scipionh commentedon Nov 26, 2025
I see, however I was under the assumption that the module created by my
TestBed.configureTestingModulewould be self sufficient.What would you say is the best way to fix things here ? Include the modules in my
tsconfig.spec.ts?JoostK commentedon Nov 26, 2025
That's for JIT (re)compiling the component, it is not taken into account during the AOT compilation.
Switch to standalone components :-) But yeah, having the same file in the compilation unit by using
tsconfig.spec.json#includeswould be the next best alternative.Scipionh commentedon Nov 27, 2025
Yeah, migrating to standalone is the plan.
Unless, I missed something obvious, I went again through the whole testing documentation, and I really feel a caveat should be added to offer light on this particular issue. Adding modules to the tsconfig.spec.json feels completely counter-intuitive.
alan-agius4 commentedon Nov 27, 2025
To resolve this issue you could update the tsconfig as below:
Alternatively, you could use JIT instead of AOT for tests.
pshurygin commentedon Feb 5, 2026
Can someone please explain how this can be considered "working as intended" if it was clearly a working and widely used scenario with v20+karma, but it no longer works in v21+vitest? I don't think NgModule or non-standalone components support is dropped or even deprecated in v21, so I would expect this to still work without the full migration to drop NgModules in favour of standalone.
I also didn't really understand this explanation:
Why is the AppModule/AppComponent is even relevant in this discussion? As we see in the reproduction scenario, CommonModule(which exports async pipe) is explicitly imported into the TestingModule itself, so it's not clear why the compiler needs something else to make this pipe usable within this module.
JeanMeche commentedon Feb 5, 2026
The main difference is that Karma use JIT by default and Vitest uses AOT by default.
Compilation assumptions are different.
JoostK commentedon Feb 5, 2026
As @JeanMeche mentions, Vitest vs Karma is not the main differentiator here, it's JIT vs AOT. When using Vitest with JIT compilation issues like the one reported won't occur, and vice versa when using AOT compiled builds for Karma you'd run into the same errors.
TestBedis runtime-only infrastructure that the AOT-compiler doesn't take into account, and arguably can't take into account sinceTestBedredeclares component declarations. Since multipleTestBedinteractions can redeclare components in different ways, there cannot be a single AOT compiled component definition. So, using the AOT compiler will compile the code as it normally would (i.e. for all@{Component,Directive,Pipe,NgModule,Injectable}decorated classes), which also means that non-standalone components require theirNgModuleto be present.pshurygin commentedon Feb 5, 2026
Thank you, this does make more sense now. I was under the impression that karma used AOT by default this whole time, as AOT has been the default compiler for the main application for 6 years now, but apparently that is not true. And so switching to v21 with Vitest also silently switches your tests from JIT to AOT, which was not obvious at all, and introduces all these module limitations.
So what are the intended preconditions to run tests in AOT mode? Would this ever only be possible if you drop the NgModules and use standalone for all of the tested components?
chore: migrate to Vitest
chore: migrate to Vitest
chore: migrate to Vitest
chore: migrate to Vitest
chore: migrate to Vitest
chore: migrate to Vitest
chore: migrate to Vitest
hlovdal commentedon Oct 26, 2026
Confirming that putting
into the configuration used by testing makes a lot of problems go away (Angular 21 project with very old roots).