Repository navigation
TestBed.overrideComponent breaks module imports with @angular/build:unit-test #33064
Description
Activity
Confirming this happens at scale in a real-world Angular 21 codebase doing a Jest → Vitest migration via
@angular/build:unit-test, and reinforcing the OP's clarification that this is distinct from #48432 — that's an older issue from Angular 15 (2022) under the legacy@angular-devkit/build-angularbuilder, with a different trigger (set: { imports: [...] }vs empty{}) and a different effect (override silently ignored vs existing imports destroyed). Our independent reproduction matches the OP's: the bug only manifests under@angular/build:unit-test; the legacy builder is unaffected. ~49 specs out of ~1,225 (~4%) in our codebase hit this exact pattern, concentrated in detail-form components where one sharedNgModulere-exports standalone components used across a feature.Test-only workarounds that don't work:
overrideComponent({ add: { imports: [TheReExportedComponent] } })— the SUT template is AOT-pre-compiled against the SUT's original imports; runtimeoverrideComponentmodifications don't reach element resolution, so the NG0304 still fires.CUSTOM_ELEMENTS_SCHEMA— silences the error but leaves the element unrendered, breaking any test that asserts on rendered output.
Workaround that does work (production code change):
- Remove the
NgModulefrom the SUT'simports: [...]and replace with direct standalone-component imports for the declarations the template actually uses. - Move any module-level providers from the NgModule's
providers: [...]to the SUT's own@Component.providers.
Mechanical per-SUT. Verified on one SUT in our codebase: the NG0304 error is gone, and the Jest sibling continues to pass (the SUT change is purely additive).
Happy to provide an isolated repro of either the failure or the workaround if it would help triage. Thanks for the original report — the detail that an empty
overrideComponent(App, {})triggers the bug saved us hours.My Environment
_ _ ____ _ ___ / \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _| / △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | | / ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | | /_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___| |___/ Angular CLI : 21.2.8 Angular : 21.2.9 Node.js : 24.14.0 Package Manager : npm 11.15.0 Operating System : darwin arm64 ┌───────────────────────────────────┬───────────────────┬───────────────────┐ │ Package │ Installed Version │ Requested Version │ ├───────────────────────────────────┼───────────────────┼───────────────────┤ │ @angular-devkit/build-angular │ 21.2.8 │ 21.2.8 │ │ @angular-devkit/core │ 21.2.8 │ 21.2.8 │ │ @angular/animations │ 21.2.9 │ 21.2.9 │ │ @angular/build │ 21.2.8 │ 21.2.8 │ │ @angular/cdk │ 21.2.8 │ 21.2.8 │ │ @angular/cli │ 21.2.8 │ 21.2.8 │ │ @angular/common │ 21.2.9 │ 21.2.9 │ │ @angular/compiler │ 21.2.9 │ 21.2.9 │ │ @angular/compiler-cli │ 21.2.9 │ 21.2.9 │ │ @angular/core │ 21.2.9 │ 21.2.9 │ │ @angular/forms │ 21.2.9 │ 21.2.9 │ │ @angular/language-service │ 21.2.9 │ 21.2.9 │ │ @angular/platform-browser │ 21.2.9 │ 21.2.9 │ │ @angular/platform-browser-dynamic │ 21.2.9 │ 21.2.9 │ │ @angular/router │ 21.2.9 │ 21.2.9 │ │ @angular/service-worker │ 21.2.9 │ 21.2.9 │ │ rxjs │ 7.8.2 │ ^7.8.2 │ │ typescript │ 5.9.3 │ ^5.9.3 │ │ vitest │ 4.1.7 │ ^4.1.7 │ │ zone.js │ 0.16.1 │ 0.16.1 │ └───────────────────────────────────┴───────────────────┴───────────────────┘Reacted by John CrimWe're affected by this in a big way - it's making migrating to vitest/the new builder much more work (and much more verbose) than it should be. Initially I thought it was a bug in
@testing-library/angular, but while working on a repro case, I found that it's a surprising bug in TestBed. Common testing scenarios like overriding the test component template or adding/updating imports of test component dependencies from modules are all broken. I can provide more repro cases if it's helpful.This is a severe bug that will add a bunch of frustration to anyone migrating to the new test builder.
My take is that this bug is a bigger problem than the Angular team perceives it to be (I'm guessing that Google isn't using the new
@angular/build:unit-testbuilder, otherwise this would get more attention), so I added some test cases to show what works/doesn't work in a minimal repro repo:https://github.com/johncrim/ng-testbed-compile-bug
Key points:
- Bug is still present and behavior unchanged in ng 22 (same behavior as ng 21). It is not specific to standalone components like TestBed.overrideComponent doesn't update standalone components angular#48432 .
- These tests work as expected in the legacy devkit/karma builder, which is deprecated. This bug should be counted as a regression, assuming that the new unit test builder should support the same test code as the legacy builder.
- These failures prevent easy migration (to the new test builder) of tests that use test helpers like
@testing-library/angular'srender(template string). - The presence of these bugs will likely add a lot of unnecessary work and frustration to teams migrating large numbers of tests to the new builder. The error messages are misleading and cause of failure difficult to determine.
- In my experience this bug also confuses AI agents / results in a lot of cycles and trying things when using AI to migrate tests to vitest/the new builder
I'm pretty sure this compile failure is related to this bug, though it may be separate. This code block compiles and runs successfully in the devkit/karma builder, but fails to build with the unit-test builder:
// Does not compile using `@angular/build:unit-test` builder, so first test can't be run // When running using unit-test builder, comment out this component and the first test. @Component({ template: `<div data-testid="test-host"><test-cmp1/></div>`, standalone: false }) class TestHostComponent { } it('creates host component with child component from module', async () => { const testBed = TestBed.configureTestingModule({ declarations: [TestHostComponent], imports: [TestModule] }); await testBed.compileComponents(); const fixture = testBed.createComponent(TestHostComponent); await expectContainsTestCmp1(fixture); });
The compile failure when using the unit-test builder is:
Application bundle generation failed. [1.551 seconds] - 2026-07-05T20:41:34.238Z X [ERROR] NG8001: 'test-cmp1' is not a known element: 1. If 'test-cmp1' is an Angular component, then verify that it is part of this module. 2. If 'test-cmp1' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. [plugin angular-compiler] src/tests/testbedNotStandaloneOverrideImports.spec.ts:31:44: 31 │ template: `<div data-testid="test-host"><test-cmp1/></div>`, ╵ ~~~~~~~~~~~~Since it's a compile failure, none of the tests run unless the block is commented out.
The core issue here is that the vite test runner builds unit tests with AOT instead of JIT (which was what the karma runner was doing).
If you set
"test": { "builder": "@angular/build:karma", "options": { "aot": true, ...You will get the same error.
The issues described here as closely related to angular/angular#65665.
Thanks for the comment @JeanMeche - I checked and verified that you're correct, that the compile failure I'm seeing with the unit-test builder can be reproduced with the
@angular-devkit/build-angular:karmabuilder by adding"aot": true.I find this kind of alarming, since it's a valid test that just doesn't work when AOT is enabled. But reading the thread in angular#65665 does help clear things up for the compile error. In short, the AOT compiler requires a separate NgModule to discover the dependencies that can be used in the non-standalone test component's template. The testing module in
configureTestingModule()can't be used as the module when AOT is enabled.Conclusion: I thought the compile error was a related or the same bug - but it is separate, and already covered by angular#65665.
If I fix that, and run the tests in the legacy devkit/karma builder with
aot=true, I get some overlapping and some different failures:Overriding a test component template succeeds in the legacy test builder and FAILs in the new one:
TestBed.configureTestingModule({ imports: [ TestHostComponent ] }) .overrideComponent(TestHostComponent, { set: { template: `<test-cmp1/><test-cmp1/>`, } }); });
Per the description of this bug above, calling
overrideComponent()breaks test component imports.Importing a standalone child component works in the new test builder and fails in the legacy one:
TestBed.configureTestingModule({ imports: [ StandaloneWrapperComponent ] }) .overrideComponent(StandaloneWrapperComponent, { set: { template: `<test-cmp1/>`, imports: [TestCmp1] } });
(which is good, b/c it's a critical workaround)
And importing test component dependencies via modules only works with JIT compilation (the legacy default) and fails in the legacy builder with aot=true, and fails in the new builder:
TestBed.configureTestingModule({ imports: [ StandaloneWrapperComponent ] }).overrideComponent(StandaloneWrapperComponent, { set: { template: `<test-cmp1/>`, imports: [TestModule] } });
All of these cases can be examined and run in my https://github.com/johncrim/ng-testbed-compile-bug test case repo.
I stand by my previous statement that these changes in behavior are a big deal for anyone migrating a large number of tests to the new test builder - especially since the old builder is deprecated so teams trying to stay on the Angular upgrade path are being pushed to migrate.
- added a commit that references this issue
on Jul 6, 2026
Command
test
Is this a regression?
The previous version in which this bug was not present was
No response
Description
Reopening from angular/angular#68363 as I don't feel it was fully answered and I later found the issue is related to the new builder.
When using the
@angular/build:unit-testbuilder,TestBed.overrideComponentbreaks imports out of modules. This happens for both vitest and karma runners, so I would assume it is connected to the build, not the test execution.The issue does not occur when using other builder like
@angular-devkit/build-angular:karmaMinimal Reproduction
Plain Angular project + packages needed for running karma
Running the test with
@angular/build:unit-testit fails for both runners withWith the
@angular-devkit/build-angular:karmait passes as expected.Also actually overriding something in
TestBed.overrideComponentdoesn't change the behaviour. I originally discovered this with a test that needs to stub a component. I left it out for simplicity here.Exception or Error
Your Environment
Anything else relevant?
No response