[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没有正确进行,但具体原因尚不清楚。

解决之道

经过如下过程,问题暂时得到了解决。

    1. 在HeroService中,注释掉了MessageService的DI。

 

    1. 错误得到解决,因此判断DI确实相关。

 

    1. 使用Angular CLI创建了另一个服务(TestService)。在TestService中,与HeroService类似,进行了MessageService的DI,并创建了相似的测试代码。

 

    1. TestService的测试代码通过了。

 

    通过比较HeroService和TestService,发现providedIn部分不同,并进行了修正,之后HeroService的测试代码通过了。
这里是修正后的代码。hero.service.spec.ts
从 ‘@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);
}
}

广告
将在 10 秒后关闭
bannerAds