NullInjectorError:在Angular 2中测试时的StaticInjectorError(DynamicTestModule)

Posted

技术标签:

【中文标题】NullInjectorError:在Angular 2中测试时的StaticInjectorError(DynamicTestModule)【英文标题】:NullInjectorError: StaticInjectorError(DynamicTestModule) When Testing in Angular 2 【发布时间】:2019-07-23 22:07:34 【问题描述】:

我是 Angular2 的新手,正在尝试在 app.component.spec.ts 文件中编写测试。我的应用程序相对简单,除了它从第三方库(由同事编写)导入 LoginComponent 和 LogoutComponent 之外。这些组件现在分别用于路由登录或注销,非常简单。运行ng serve 编译正常,应用程序“顺利”运行。但是,运行 ng test 时会出现此错误:

NullInjectorError: StaticInjectorError(DynamicTestModule)[LogoutComponent -> SessionService]: 
  StaticInjectorError(Platform: core)[LogoutComponent -> SessionService]: 
    NullInjectorError: No provider for SessionService!

LogoutComponent 是从不同的项目导入的。此错误是否意味着我需要进入该项目并进行一些更改,或者我应该在我的项目中以某种方式模拟 SessionService?

规格代码:

import  from 'jasmine';
import async, TestBed from '@angular/core/testing';
import RouterTestingModule from '@angular/router/testing';
import AuthErrorStateService, LogoutComponent from '@custom-library';

import AppComponent from './app.component';
import AppErrorStateService from './core/error-states/app-error-state.service';
import TopNavComponent from './core/top-nav/top-nav.component';

describe('AppComponent', () => 
  beforeEach(async(() => 
    TestBed
        .configureTestingModule(
          imports: [RouterTestingModule],
          providers: [
            AppErrorStateService, AuthErrorStateService
          ],
          declarations: [AppComponent, TopNavComponent, LogoutComponent],
        )
        .compileComponents();
  ));

  it('should create the app', () => 
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  );

  it(`should have as title 'My App'`, () => 
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app.title).toEqual('My App');
  );

  it('should render title in a h1 tag', () => 
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h1').textContent).toEqual('Welcome to My App!');
  );
);

【问题讨论】:

有助于查看您的TestBed 配置,但看起来您没有将SessionService 放入配置对象的providers 数组中。 您好,尝试将提供者添加到 spec.ts 文件中的提供者数组中。 @TheHeadRush 如果你说的是TestBed 配置对象,我没有——因为SessionService 在项目中根本没有定义。它在正在导入的项目 LogoutComponent 中定义。 @JosefKatič 提供者(SessionService)不是来自这个项目——它来自另一个。如果我将它导入这个项目并将其放入 providers 数组中,Karma 只会大喊没有提供下一个服务(SessionServiceApi)等等。 您的设置实例化了多个组件。您要么需要将注入TopNavComponentLogoutComponent 的所有服务添加到提供程序数组(使其成为集成测试),要么从declarations 中删除额外的组件并将schema: [CUSTOM_ELEMENTS_SCHEMA] 添加到配置中。跨度> 【参考方案1】:

问题是像这样在TestBed 中声明多个组件

 declarations: [AppComponent, TopNavComponent, LogoutComponent]

导致在测试调用compileComponents() 时实例化多个组件。发生这种情况时,declarations 数组中的每个组件都需要在providers 数组中声明其依赖项才能完成实例化。声明的组件之一依赖于SessionService,但该服务在提供程序中不存在,因此您将获得NullInjectorError

有两种解决方案:

只在declarations数组中声明一个组件并添加 schemas: [ CUSTOM_ELEMENTS_SCHEMA ]TestBed 配置 对象 继续声明多个组件并添加所有 每个组件的依赖项(或其模拟) providers数组

【讨论】:

就我而言,我也错过了一项服务。我认为这个问题的通用答案是您可能缺少一项服务。 很遗憾,此错误未显示女巫服务或缺少提供者。在一个大组件中,找到正确的组件很麻烦。 @Experimenter Angular 9 确实提供了依赖链并确定了有问题的提供者。 @TheHeadRush 有什么例子吗? 我的问题已通过使用 @Input 从组件接收数据对象得到解决,这是导致此问题的原因。

以上是关于NullInjectorError:在Angular 2中测试时的StaticInjectorError(DynamicTestModule)的主要内容,如果未能解决你的问题,请参考以下文章

Angular 9:NullInjectorError:没有 CompilerFactory 的提供者

NullInjectorError:没有提供 DecimalPipe

Angular:NullInjectorError:没有HttpClient的提供者[重复]

角度业力 - NullInjectorError:InjectionToken 配置没有提供者

NullInjectorError:没有提供 ElementRef

在 Angular 6 中,我在组件中收到错误“NullInjectorError: No provider for Store”