我尝试在我的应用程序中使用 Angular 注入令牌,但它一直导致我的单元测试失败。
这是一个演示该问题的存储库:
https://github.com/shadow1349/nx-filereplacementissue/tree/main
如果您检查主分支,请运行
npm install
,然后运行 npx nx run test:test
您将看到以下错误:
NullInjectorError: R3InjectorError(Standalone[ComponentsComponent])
[InjectionToken TEST_INJECTION_TOKEN -> InjectionToken TEST_INJECTION_TOKEN -> InjectionToken TEST_INJECTION_TOKEN]:
NullInjectorError: No provider for InjectionToken TEST_INJECTION_TOKEN!
这是我的注入令牌:https://github.com/shadow1349/nx-filereplacementissue/blob/main/shared/injection-tokens/src/index.ts
export const TEST_INJECTION_TOKEN = new InjectionToken<BehaviorSubject<string>>(
'TEST_INJECTION_TOKEN'
);
我的应用程序配置,位于此处:https://github.com/shadow1349/nx-filereplacementissue/blob/main/test/src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { TEST_INJECTION_TOKEN } from '@test-filereplacements/injection-tokens';
import { BehaviorSubject } from 'rxjs';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(appRoutes),
{
provide: TEST_INJECTION_TOKEN,
useValue: new BehaviorSubject<string>('Hello World'),
},
],
};
然后我有一个共享组件导入到我的应用程序组件中,称为 ComponentsComponent,位于此处:
https://github.com/shadow1349/nx-filereplacementissue/blob/main/test/src/app/app.component.ts
这里:
// app component
import { Component } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NxWelcomeComponent } from './nx-welcome.component';
import { ComponentsComponent } from '@test-filereplacements/components';
@Component({
standalone: true,
imports: [NxWelcomeComponent, RouterModule, ComponentsComponent],
selector: 'test-filereplacements-root',
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
export class AppComponent {}
//components.component.ts
import { Component, Inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TEST_INJECTION_TOKEN } from '@test-filereplacements/injection-tokens';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'test-filereplacements-components',
standalone: true,
imports: [CommonModule],
templateUrl: './components.component.html',
styleUrl: './components.component.css',
})
export class ComponentsComponent {
constructor(
@Inject(TEST_INJECTION_TOKEN) public testToken: BehaviorSubject<string>
) {
console.log('testToken', this.testToken);
}
}
当您运行时,这一切都正常工作
npx nx run test:serve --configuration=development
它会很好地控制台日志。
这就是您会遇到问题的地方。如果您使用 Jest 运行测试,它将通过。但是,当您运行
npx nx run test:test
时,它会失败并显示:
NullInjectorError: R3InjectorError(Standalone[ComponentsComponent])
[InjectionToken TEST_INJECTION_TOKEN -> InjectionToken TEST_INJECTION_TOKEN -> InjectionToken TEST_INJECTION_TOKEN]:
NullInjectorError: No provider for InjectionToken TEST_INJECTION_TOKEN!
我知道您要问的第一个问题是,在 app.component.ts 中我是否有注入令牌的提供者,是的,我有。你可以在这里看到:
https://github.com/shadow1349/nx-filereplacementissue/blob/main/test/src/app/app.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { NxWelcomeComponent } from './nx-welcome.component';
import { RouterTestingModule } from '@angular/router/testing';
import { TEST_INJECTION_TOKEN } from '@test-filereplacements/injection-tokens';
import { BehaviorSubject } from 'rxjs';
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent, NxWelcomeComponent, RouterTestingModule],
providers: [
{
provide: TEST_INJECTION_TOKEN,
useValue: new BehaviorSubject<string>('Hello World'),
},
],
}).compileComponents();
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should exist', () => {
expect(component).toBeTruthy();
});
});
但是,它仍然认为注入令牌不存在。有谁知道为什么吗?
谢谢!
NullInjectorError: R3InjectorError(Standalone[ComponentsComponent])
[InjectionToken TEST_INJECTION_TOKEN -> InjectionToken TEST_INJECTION_TOKEN -> InjectionToken TEST_INJECTION_TOKEN]:
NullInjectorError: No provider for InjectionToken TEST_INJECTION_TOKEN!
要修复此错误,您需要在组件中提供 InjectionToken,如下所示:
@Component({
selector: 'test-filereplacements-components',
standalone: true,
imports: [CommonModule],
templateUrl: './components.component.html',
styleUrl: './components.component.css',
providers: [
{
provide: TEST_INJECTION_TOKEN,
useValue: new BehaviorSubject<string>('Hello World'),
},
]
})
export class ComponentsComponent {
constructor(
@Inject(TEST_INJECTION_TOKEN) public testToken: BehaviorSubject<string>
) {
console.log('testToken', this.testToken);
}
}