角度7:NullInjectorError测试失败,服务仍可在组件中运行

时间:2019-03-14 11:08:08

标签: angular testing karma-jasmine

由于服务的NullInjector错误,我的Karma测试失败。

  • 该服务正在组件中运行(是否存在测试问题而不是组件问题?),
  • 服务注入可用于其他组件,并且它们的测试通过

类似问题的解决方案与声明提供者有关。就我而言,我已经声明了提供程序(请参见下文),并且该服务在组件内部运行。

Error: StaticInjectorError[LoginComponent -> AuthenticationProvider]: 
    NullInjectorError: No provider for AuthenticationProvider! 

服务:

@Injectable()
export class AuthenticationProvider {
  uri: string
  constructor(
    private http: HttpClient,
     private config: SancusConfiguration,
    ) 
    {

  }

测试失败:

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ AppModule ],
      declarations: [  ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

我已经在NgModule的提供程序中列出了AuthenticationProvider:

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    ....
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    CollapseModule.forRoot(),
    ReactiveFormsModule,
    HttpClientModule
  ],
  schemas: [ NO_ERRORS_SCHEMA ],
  providers: [
  AuthenticationProvider,
   .....
  ],

  bootstrap: [AppComponent]
})
export class AppModule { }

2 个答案:

答案 0 :(得分:1)

测试必须完全独立于您的模块。

因此,您不应该在测试中使用imports: [ AppModule ]

您应该导入组件中使用的每个组件和服务(或它们的模拟),而不能导入更多。因为如果添加更多元素,则测试将无法验证组件的真实状态。

示例:

TestBed.configureTestingModule({
  imports: [
    SharedModule,
    TranslateModule
  ],
  declarations: [
    LoginComponent,
    MockAnotherComponent,
  ],
  providers: [
    AuthenticationProvider,
    {
      provide: Router,
      useValue: mockRouter
    }
  ]
})

... 

@Component({
  selector: 'app-another-component',
  template: '<ng-content></ng-content>'
})
export class MockAnotherComponent{
  @Input()
  title: string = null;
}

答案 1 :(得分:1)

  • 由于AppModule不会导出其提供程序,因此您必须在测试模块中列出您的提供程序。
  • 您也不应加载整个AppModule来仅测试LoginComponent
  • 您将不得不嘲笑这些提供程序,因为它们似乎正在进行网络呼叫。

代码示例:

TestBed.configureTestingModule({
  providers: [{provide: AuthenticationProvider,  useValue: mockProvider}, ... ],
  declarations: []
})