[Angular, Jest] 解决 TypeError: Cannot read property ‘ɵprov’ of undefined 错误
请概括
当我在为Angular的服务类编写测试代码时,遇到了以下错误而陷入困境。
TypeError: Cannot read property 'ɵprov' of undefined
或者
Can't resolve all parameters for HeroService: (?).
总的来说,尽管我们不知道具体原因,但通过将服务类@Injectable内部的代码更改为以下内容,问题得以解决。
@Injectable({
- providedIn: 'root',
+ providedIn: 'root'
})
export class HeroService {
只是删除了逗号而已…如果有人知道原因,请在评论区告诉我,感激不尽。
(2020年11月15日更新)
问题已解决。(逗号确实无关紧要。)
在tsconfig的compilerOptions中添加以下参数后,错误已解决。
{
"compilerOptions": {
+ "emitDecoratorMetadata": true
},
}
根据这个jest-preset-angular,据说Angular8及以上版本可能会缺少元数据,取决于CLI的配置。
使用Angular 8及更高版本时,Angular CLI的工作方式可能发生了变化,可能会导致元数据丢失。
添加此设置并运行后,测试通过了。
顺便提一下,如果更改设置后仍然没有变化,可以尝试禁用缓存并运行,或许会有好处。
$ jest hero.service --no-cache
(追加結束)
环境
$ ng --version
Angular CLI: 10.1.7
Node: 12.16.1
OS: win32 x64
Angular: 10.1.6
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1001.7
@angular-devkit/build-angular 0.1002.0
@angular-devkit/core 10.1.7
@angular-devkit/schematics 10.1.7
@angular/cli 10.1.7
@schematics/angular 10.1.7
@schematics/update 0.1001.7
rxjs 6.6.3
typescript 4.0.5
经过
我试图对Angular教程《英雄之旅》中的“4.添加服务”部分的示例代码进行测试代码的实现。
测验目标类别如下。直接下载的文件。
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { MessageService } from './message.service';
@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor(private messageService: MessageService) { }
getHeroes(): Observable<Hero[]> {
// TODO: send the message _after_ fetching the heroes
this.messageService.add('HeroService: fetched heroes');
return of(HEROES);
}
}
作为回应,实施以下测试代码。
import { TestBed } from '@angular/core/testing';
import { HeroService } from 'src/app/hero.service';
describe('TestHeroService', () => {
let heroService: HeroService;
beforeEach(() => {
TestBed.configureTestingModule({});
heroService = TestBed.inject(HeroService);
});
it('should be created', () => {
expect(heroService).toBeTruthy();
});
});
打算快速测试实例化,然后写测试方法,一开始如前所述。
TypeError: Cannot read property 'ɵprov' of undefined
发生了一个错误。
经过调查,发现DI没有正确进行,但具体原因尚不清楚。
解决之道
经过如下过程,问题暂时得到了解决。
-
- 在HeroService中,注释掉了MessageService的DI。
-
- 错误得到解决,因此判断DI确实相关。
-
- 使用Angular CLI创建了另一个服务(TestService)。在TestService中,与HeroService类似,进行了MessageService的DI,并创建了相似的测试代码。
-
- TestService的测试代码通过了。
- 通过比较HeroService和TestService,发现providedIn部分不同,并进行了修正,之后HeroService的测试代码通过了。
从 ‘@angular/core’ 导入 { Injectable }。
从 ‘rxjs’ 导入 { Observable, of }。
从 ‘./hero’ 导入 { Hero }。
从 ‘./mock-heroes’ 导入 { HEROES }。
从 ‘./message.service’ 导入 { MessageService }。
@Injectable({
providedIn: ‘root’ // 只是删除了逗号
})
export class HeroService {
constructor(private messageService: MessageService) { }
getHeroes(): Observable<Hero[]> {
// TODO: 在获取英雄后发送消息
this.messageService.add(‘HeroService: fetched heroes’);
return of(HEROES);
}
}