Angular 19: Unexpected "HostComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call
Closed this issue ยท 14 comments
Is this a regression?
No
Description
I just updated a library to use Angular 19 and Spectator 19 and I'm having the following issue for all my tests:
Failed: Unexpected "HostComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "HostComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?
at forEach (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:769:23)
at Array.forEach (<anonymous>)
at assertNoStandaloneComponents (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:765:11)
at TestBedCompiler.configureTestingModule (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:844:13)
at TestBedImpl.configureTestingModule (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:1974:23)
at Function.configureTestingModule (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:1789:37)
at UserContext.apply (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@ngneat/spectator/fesm2022/ngneat-spectator.mjs:1707:17)
at _ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone.js:369:28)
at AsyncTestZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:892:39)
at ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:2079:39)
Here is the test:
describe('ng-ui-badge', () => {
let spectator: SpectatorHost<BadgeComponent>;
const createComponent = createHostFactory(BadgeComponent);
it('should display the value passed into the value property', () => {
spectator = createComponent(`<ng-ui-badge value="12"></ng-ui-badge>`);
expect(spectator.element).toHaveText('12');
});
});
And the badge component in itself is not really complex. It's a simple component with the "standalone" flag set to "true". I don't think it's related to the component itself as I have tests for 30+ components and they all fail with the same error.
I tried by using the imports
array but it did not change anything:
const createComponent = createHostFactory({
component: BadgeComponent,
imports: [
BadgeComponent
]
});
I also try setting declareComponent
to false with no luck.
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
Failed: Unexpected "HostComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "HostComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?
at forEach (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:769:23)
at Array.forEach (<anonymous>)
at assertNoStandaloneComponents (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:765:11)
at TestBedCompiler.configureTestingModule (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:844:13)
at TestBedImpl.configureTestingModule (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:1974:23)
at Function.configureTestingModule (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2022/testing.mjs:1789:37)
at UserContext.apply (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@ngneat/spectator/fesm2022/ngneat-spectator.mjs:1707:17)
at _ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone.js:369:28)
at AsyncTestZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:892:39)
at ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:2079:39)
Please provide the environment you discovered this bug in
Angular CLI: 19.0.0
Node: 20.18.0
Package Manager: yarn 1.22.22
OS: win32 x64
Angular: 19.0.0
... animations, cli, common, compiler, compiler-cli, core
... elements, forms, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1900.0
@angular-devkit/build-angular 19.0.0
@angular-devkit/core 19.0.0
@angular-devkit/schematics 19.0.0
@ngneat/spectator 19.0.0
@schematics/angular 19.0.0
ng-packagr 19.0.0
rxjs 7.8.1
typescript 5.5.4
zone.js 0.15.0
Anything else?
No response
Do you want to create a pull request?
No
I have the same issue with MockComponent
Failed: Unexpected "MockOfImageRevertButtonComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "MockOfImageRevertButtonComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?
adding this to imports did nothing
imports: [
MatDialogModule,
BrowserAnimationsModule,
ImageEditorComponent,
MockComponent(ImageRevertButtonComponent),
MockComponent(ImageAttributesFormComponent),
],
I now have a ton of broken tests after the Angular upgrade
So there is a workaround that i got to work for pipes
and directives
.
Create a Dummy component and specify standalone: false
.
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'lib-ngneat-host-component',
template: '',
standalone: false,
})
export class StandaloneHostFixComponent {}
Then for a pipe or override the host
option with the component.
Pipe example:
const createPipe: SpectatorPipeFactory<CcDatePipe, StandaloneHostFixComponent> = createPipeFactory({
pipe: CustomDatePipe,
host: StandaloneHostFixComponent,
});
Directive example:
createDirectiveFactory({
directive: CustomDirective,
host: StandaloneHostFixComponent
});
@ssougnez For your case this should work.
const createComponent = createHostFactory({
component: BadgeComponent,
host: StandaloneHostFixComponent
});
Basically the issue is this component here because it does not specify standalone: false
so when using NG19 it will automatically be standalone: true
which will cause the error. But change it to standalone: false
will lead to other issues so i couldn't come up with an PR without updating angular.
This is not a work around for the case of mocking standalone components which is what I need
So there is a workaround that i got to work for
pipes
anddirectives
.Create a Dummy component and specify
standalone: false
.import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'lib-ngneat-host-component', template: '', standalone: false, }) export class StandaloneHostFixComponent {}
Then for a pipe or override the
host
option with the component.Pipe example:
const createPipe: SpectatorPipeFactory<CcDatePipe, StandaloneHostFixComponent> = createPipeFactory({ pipe: CustomDatePipe, host: StandaloneHostFixComponent, });
Directive example:
createDirectiveFactory({ directive: CustomDirective, host: StandaloneHostFixComponent });
@ssougnez For your case this should work.
const createComponent = createHostFactory({ component: BadgeComponent, host: StandaloneHostFixComponent });
Basically the issue is this component here because it does not specify
standalone: false
so when using NG19 it will automatically bestandalone: true
which will cause the error. But change it tostandalone: false
will lead to other issues so i couldn't come up with an PR without updating angular.
Thanks a lot for the investigation, but wouldn't it be more clean to have a new major version of the library only supporting ng 19 and taking into account standalone component?
So there is a workaround that i got to work for
pipes
anddirectives
.
Create a Dummy component and specifystandalone: false
.import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'lib-ngneat-host-component', template: '', standalone: false, }) export class StandaloneHostFixComponent {}
Then for a pipe or override the
host
option with the component.
Pipe example:const createPipe: SpectatorPipeFactory<CcDatePipe, StandaloneHostFixComponent> = createPipeFactory({ pipe: CustomDatePipe, host: StandaloneHostFixComponent, });
Directive example:
createDirectiveFactory({ directive: CustomDirective, host: StandaloneHostFixComponent });
@ssougnez For your case this should work.
const createComponent = createHostFactory({ component: BadgeComponent, host: StandaloneHostFixComponent });
Basically the issue is this component here because it does not specify
standalone: false
so when using NG19 it will automatically bestandalone: true
which will cause the error. But change it tostandalone: false
will lead to other issues so i couldn't come up with an PR without updating angular.Thanks a lot for the investigation, but wouldn't it be more clean to have a new major version of the library only supporting ng 19 and taking into account standalone component?
Sure you are right but this project doesn't look to active does it? So the last release isn't even in npm ans over 2 months ago so don't know when an update will come. So we will have a workaround for now to proceede with NG19 and if there is an major update fine if not we will move away from it.
This is not a work around for the case of mocking standalone components which is what I need
The workaround is just recreating the current behaviour of the HostComponent in the project but with a NG19 component. The componen you are testing is still standalone his is just the "host component" around your component that you set via component
. We are using it with standalone components
So there is a workaround that i got to work for
pipes
anddirectives
.
Create a Dummy component and specifystandalone: false
.import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'lib-ngneat-host-component', template: '', standalone: false, }) export class StandaloneHostFixComponent {}
Then for a pipe or override the
host
option with the component.
Pipe example:const createPipe: SpectatorPipeFactory<CcDatePipe, StandaloneHostFixComponent> = createPipeFactory({ pipe: CustomDatePipe, host: StandaloneHostFixComponent, });
Directive example:
createDirectiveFactory({ directive: CustomDirective, host: StandaloneHostFixComponent });
@ssougnez For your case this should work.
const createComponent = createHostFactory({ component: BadgeComponent, host: StandaloneHostFixComponent });
Basically the issue is this component here because it does not specify
standalone: false
so when using NG19 it will automatically bestandalone: true
which will cause the error. But change it tostandalone: false
will lead to other issues so i couldn't come up with an PR without updating angular.Thanks a lot for the investigation, but wouldn't it be more clean to have a new major version of the library only supporting ng 19 and taking into account standalone component?
Sure you are right but this project doesn't look to active does it? So the last release isn't even in npm ans over 2 months ago so don't know when an update will come. So we will have a workaround for now to proceede with NG19 and if there is an major update fine if not we will move away from it.
Yeah, this is more my concern actually.
I browsed a bit the latest issue and there don't seem to have much activity.
I'm considering dropping this library and have a look at another one...
As for you other answer, I guess it's a good workaround that I'll probably use waiting for a real solution to be implemented or for me to have time to replace this library.
Thanks a lot :-)
I'm working on a PR for this.
The lead maintainer has been quite helpful in accepting and coaching PRs in the past - I wouldn't get down on the library, just contribute! This is what open-source dev tools are all about.
This is not a work around for the case of mocking standalone components which is what I need
@carflynn2009 - to mock a standalone component, this bugfix isn't needed. You can do it right now by using the MockComponent()
fn from ng-mocks
(which is what spectator uses for its mocks: []
array), and put it under imports:
import { MockComponent } from 'ng-mocks';
...
let spectator: Spectator<FooComponent>;
const createComponent = createComponentFactory( // Or whatever factory
{
component: FooComponent,
imports: [
MockComponent(InnerComponent)
]
});
This is not a work around for the case of mocking standalone components which is what I need
@carflynn2009 - to mock a standalone component, this bugfix isn't needed. You can do it right now by using the
MockComponent()
fn fromng-mocks
(which is what spectator uses for itsmocks: []
array), and put it under imports:import { MockComponent } from 'ng-mocks'; ... let spectator: Spectator<FooComponent>; const createComponent = createComponentFactory( // Or whatever factory { component: FooComponent, imports: [ MockComponent(InnerComponent) ] });
Going back to my original post this is exactly what I was doing and it still gives the same error , I cannot mock standalone components since angular 19
I have the same issue with
MockComponent
Failed: Unexpected "MockOfImageRevertButtonComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "MockOfImageRevertButtonComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?
adding this to imports did nothing
imports: [ MatDialogModule, BrowserAnimationsModule, ImageEditorComponent, MockComponent(ImageRevertButtonComponent), MockComponent(ImageAttributesFormComponent), ],
I now have a ton of broken tests after the Angular upgrade
@johncrim if you look at the code I have it does not work
@carflynn2009 - I have tests with MockComponent
in imports and it works as expected with ng19. There's nothing I see in your code snippet that is materially different from what is working for me.
Did you try ng cache clean
?
That is what I I thought that it should just work but as soon as I upgraded every test I have with mock fails ,
I will try ng clean
I have the same issue with
MockComponent
Failed: Unexpected "MockOfImageRevertButtonComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "MockOfImageRevertButtonComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?
adding this to imports did nothing
imports: [ MatDialogModule, BrowserAnimationsModule, ImageEditorComponent, MockComponent(ImageRevertButtonComponent), MockComponent(ImageAttributesFormComponent), ],
I now have a ton of broken tests after the Angular upgrade
@johncrim if you look at the code I have it does not work
That is what I I thought that it should just work but as soon as I upgraded every test I have with mock fails ,
I will try ng clean
@carflynn2009 did your issues disappear when upgrading to the latest spectator version.
After the upgrade I still run into this
Failed: Unexpected "MockOfImageRevertButtonComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "MockOfImageRevertButtonComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?