Angular / Ivy error : Error: Token InjectionToken XXXXXXXXX is missing a ɵprov definition

Angular / Ivy error : Error: Token InjectionToken XXXXXXXXX is missing a ɵprov definition

更新到Angular 9 / Ivy 编译器后出现错误

ERROR Error: Token InjectionToken XXXXXXXXX is missing a ɵprov definition.
    at injectableDefOrInjectorDefFactory (vendor.js:47105)
    at providerToFactory (vendor.js:47210)
    at resolveProvider (vendor.js:56430)

如果您尝试使用 undefinednull 显式覆盖继承的可注射剂,就会发生这种情况。

在 Angular 8 这没问题

    {
        provide: AMBIENT_CART,
        useExisting: undefined
    }

对于Angular9需要改为

    {
        provide: AMBIENT_CART,
        useValue: undefined
    }

如果您好奇:就我而言,我这样做是出于安全原因,以确保我没有错误地使用这种特殊的注射剂。

从 Angular 8 --> 9 升级后 运行 ng 测试时,我遇到了同样的错误: "Error: Token InjectionToken apiToken is missing a ɵprov definition."

我对此的解决方案非常简单——规格文件中有一个拼写错误,我猜这在 Angular 8 中无关紧要,但在 Angular 9 中呢?下面的最后一个 'useValue' 写错了 'usevalue'。这么隐晦的错误!

TestBed.configureTestingModule({ 
    imports: [ HttpClientTestingModule ], 
    providers: [ 
        { provide: ApiService, useValue: apiService }, 
        { provide: ProductsApiService, useValue: productsService }, 
        { provide: apiToken, useValue: mockApiToken } 
    ] 
});

我在将应用程序从 Angular 8 升级到 Angular 10 后 运行 进行单元测试时开始收到此错误。出现此问题是因为现有规范文件正在使用 value 而不是 providers 数组中的 useValue,如下例所示。通过将其更改为 useValue.

解决了该问题
    beforeEach(async(() => {
    void TestBed.configureTestingModule({
        declarations: [
            MockPipe(TranslatePipe),
        ],
        imports: [
            HttpClientTestingModule,
        ],
        providers: [
            FormBuilder,
            MessageService,
            { provide: MESSAGES_TOKEN, value: {} }, //changed to useValue
        ]
    }).compileComponents();
}));

当我将Angular更新到版本>=9时我遇到了同样的错误(Token InjectionToken XxXxXxXx 缺少 ɵprov 定义 ),特别是当我 运行 测试时,这些测试的提供者为 MatDialogRefMAT_DIALOG_DATA 来自 Angular Material.

我的解决方案是替换 beforeEach() 部分中的提供程序配置。看看:

之前:

import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';

beforeEach(async(() => {
            TestBed.configureTestingModule({
                    imports : [
                        ...
                    ],
                    declarations: [
                        ...
                    ],
                    providers: [
                        { provide: MatDialogRef },
                        { provide: MAT_DIALOG_DATA }
                    ]
            }).compileComponents();

    })); 

之后:

import { MAT_DIALOG_DEFAULT_OPTIONS } from '@angular/material/dialog';

beforeEach(async(() => {
            TestBed.configureTestingModule({
                    imports : [
                        ...
                    ],
                    declarations: [
                        ...
                    ],
                    providers: [{
                        provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: {hasBackdrop: false}
                    }]
            }).compileComponents();