测试时出现 NullInjectorError
NullInjectorError while testing
我在 Angular 12 中进行 运行 ng 测试时遇到以下问题:
NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL ->
BaseURL]: NullInjectorError: No provider for BaseURL! error
properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'BaseURL',
'BaseURL' ] }) NullInjectorError:
R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]:
NullInjectorError: No provider for BaseURL!
at NullInjector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11101:1)
at R3Injector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11268:1)
at R3Injector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11268:1)
at NgModuleRef.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:25332:1)
at Object.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:25046:1)
at lookupTokenUsingModuleInjector (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3342:1)
at getOrCreateInjectable (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3454:1)
at ɵɵdirectiveInject (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:14737:1)
at NodeInjectorFactory.MenuComponent_Factory [as factory] (ng:///MenuComponent/ɵfac.js:5:7)
at getNodeInjectable (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3549:1)
Error: Expected undefined to be truthy.
at
at UserContext. (http://localhost:9876/karma_webpack/webpack:/src/app/menu/menu.component.spec.ts:46:23)
at ZoneDelegate.invoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:372:1)
at ProxyZoneSpec.onInvoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:287:1)
spec.ts 的代码是:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuComponent } from './menu.component';
import { DishService } from '../services/dish.service';
describe('MenuComponent', () => {
let component: MenuComponent;
let fixture: ComponentFixture<MenuComponent>;
const mockDishService = {
getDishes: () => {
return {
id: '000',
name: 'nnnnn'
}
}
}
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [],
declarations: [ MenuComponent ],
providers: [
{ provide: DishService, useValue: mockDishService },
]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MenuComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
组件代码为:
import { Component, OnInit, Inject } from '@angular/core';
import { Dish } from '../shared/dish';
import { DishService } from '../services/dish.service';
import { flyInOut, expand } from '../animations/app.animation';
@Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.scss'],
// tslint:disable-next-line:use-host-property-decorator
host: {
'[@flyInOut]': 'true',
'style': 'display: block;'
},
animations: [
flyInOut(),
expand()
]
})
export class MenuComponent implements OnInit {
dishes!: Dish[];
errMess: string;
constructor(private dishService: DishService,
@Inject ('BaseURL') public baseURL) { }
ngOnInit(): void {
this.dishService.getDishes().subscribe((dishes => this.dishes = dishes), errMess => this.errMess = <any>errMess);
}
}
我正在使用 baseURL 来获取 db.json 文件的信息,而 运行 json-server --watch db.json 来模拟我得到来自服务器的信息,所以我有一个名为 baseurl.ts 的共享 .ts 文件,其中包含以下代码:
export const baseURL = 'http://localhost:3000';
并且在 app.module.ts 中我导入了 const
import { baseURL } from './shared/baseurl';
我将其添加为同一 app.module.ts 文件中的提供程序:
providers: [
{ provide: 'BaseURL', useValue: baseURL }
],
非常感谢有人帮助解决这个错误
问题 1:NullInjectorError
此错误消息显示为您的 DishComponent
需要 BaseURL
注入 [@Inject ('BaseURL')
]。
NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]: NullInjectorError: No provider for BaseURL!
问题 1 的解决方案
确保在 providers
部分添加 BaseURL
进行单元测试。
const baseUrl = "your Base URL";
beforeEach(async () => {
await TestBed.configureTestingModule({
...
providers: [
{ provide: DishService, useValue: mockDishService },
{ provide: 'BaseURL', useValue: baseUrl },
]
})
.compileComponents();
});
问题 2:Return mockDishService.getDishes()
的错误值
来自MenuComponent
,预计dishService.getDishes()
return Observable<Menu[]>
或Observable<any[]>
类型的值。
dishes!: Dish[];
this.dishService.getDishes().subscribe((dishes => this.dishes = dishes), errMess => this.errMess = <any>errMess);
而mockDishService.getDishes()
return是any
或Menu
类型的值,returned的数据是不匹配的。
const mockDishService = {
getDishes: () => {
return {
id: '000',
name: 'nnnnn',
};
},
};
因此您将收到如下错误消息:
TypeError: this.dishService.getDishes(...).subscribe is not a function
问题 2 的解决方案:
确保 mockDishService.getDishes()
return 的 Observable<Menu[]>
或 Observable<any[]>
类型的值与真实的 dishService.getDishes()
.
匹配
import { of } from 'rxjs';
const mockDishService = {
getDishes: () => {
return of([
{
id: '000',
name: 'nnnnn',
},
]);
},
};
我在 Angular 12 中进行 运行 ng 测试时遇到以下问题:
NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]: NullInjectorError: No provider for BaseURL! error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'BaseURL', 'BaseURL' ] }) NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]:
NullInjectorError: No provider for BaseURL! at NullInjector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11101:1) at R3Injector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11268:1) at R3Injector.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11268:1) at NgModuleRef.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:25332:1) at Object.get (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:25046:1) at lookupTokenUsingModuleInjector (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3342:1) at getOrCreateInjectable (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3454:1) at ɵɵdirectiveInject (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:14737:1) at NodeInjectorFactory.MenuComponent_Factory [as factory] (ng:///MenuComponent/ɵfac.js:5:7) at getNodeInjectable (http://localhost:9876/karma_webpack/webpack:/node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:3549:1)Error: Expected undefined to be truthy. at at UserContext. (http://localhost:9876/karma_webpack/webpack:/src/app/menu/menu.component.spec.ts:46:23) at ZoneDelegate.invoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:372:1) at ProxyZoneSpec.onInvoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:287:1)
spec.ts 的代码是:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuComponent } from './menu.component';
import { DishService } from '../services/dish.service';
describe('MenuComponent', () => {
let component: MenuComponent;
let fixture: ComponentFixture<MenuComponent>;
const mockDishService = {
getDishes: () => {
return {
id: '000',
name: 'nnnnn'
}
}
}
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [],
declarations: [ MenuComponent ],
providers: [
{ provide: DishService, useValue: mockDishService },
]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MenuComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
组件代码为:
import { Component, OnInit, Inject } from '@angular/core';
import { Dish } from '../shared/dish';
import { DishService } from '../services/dish.service';
import { flyInOut, expand } from '../animations/app.animation';
@Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.scss'],
// tslint:disable-next-line:use-host-property-decorator
host: {
'[@flyInOut]': 'true',
'style': 'display: block;'
},
animations: [
flyInOut(),
expand()
]
})
export class MenuComponent implements OnInit {
dishes!: Dish[];
errMess: string;
constructor(private dishService: DishService,
@Inject ('BaseURL') public baseURL) { }
ngOnInit(): void {
this.dishService.getDishes().subscribe((dishes => this.dishes = dishes), errMess => this.errMess = <any>errMess);
}
}
我正在使用 baseURL 来获取 db.json 文件的信息,而 运行 json-server --watch db.json 来模拟我得到来自服务器的信息,所以我有一个名为 baseurl.ts 的共享 .ts 文件,其中包含以下代码:
export const baseURL = 'http://localhost:3000';
并且在 app.module.ts 中我导入了 const
import { baseURL } from './shared/baseurl';
我将其添加为同一 app.module.ts 文件中的提供程序:
providers: [
{ provide: 'BaseURL', useValue: baseURL }
],
非常感谢有人帮助解决这个错误
问题 1:NullInjectorError
此错误消息显示为您的 DishComponent
需要 BaseURL
注入 [@Inject ('BaseURL')
]。
NullInjectorError: R3InjectorError(DynamicTestModule)[BaseURL -> BaseURL]: NullInjectorError: No provider for BaseURL!
问题 1 的解决方案
确保在 providers
部分添加 BaseURL
进行单元测试。
const baseUrl = "your Base URL";
beforeEach(async () => {
await TestBed.configureTestingModule({
...
providers: [
{ provide: DishService, useValue: mockDishService },
{ provide: 'BaseURL', useValue: baseUrl },
]
})
.compileComponents();
});
问题 2:Return mockDishService.getDishes()
来自MenuComponent
,预计dishService.getDishes()
return Observable<Menu[]>
或Observable<any[]>
类型的值。
dishes!: Dish[];
this.dishService.getDishes().subscribe((dishes => this.dishes = dishes), errMess => this.errMess = <any>errMess);
而mockDishService.getDishes()
return是any
或Menu
类型的值,returned的数据是不匹配的。
const mockDishService = {
getDishes: () => {
return {
id: '000',
name: 'nnnnn',
};
},
};
因此您将收到如下错误消息:
TypeError: this.dishService.getDishes(...).subscribe is not a function
问题 2 的解决方案:
确保 mockDishService.getDishes()
return 的 Observable<Menu[]>
或 Observable<any[]>
类型的值与真实的 dishService.getDishes()
.
import { of } from 'rxjs';
const mockDishService = {
getDishes: () => {
return of([
{
id: '000',
name: 'nnnnn',
},
]);
},
};