Angular 7:NullInjectorError用于测试失败,服务仍在组件中工作

问题描述 投票:0回答:2

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

  • 服务IS在组件中工作(测试问题而不是组件?),
  • 服务注入适用于其他组件,并且它们的测试通过

类似问题的解决方案涉及声明提供者。在我的情况下,我已经声明了一个提供者(见下文),该服务在组件内部工作。

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 { }
angular testing karma-jasmine
2个回答
1
投票
  • 您必须在测试模块中列出您的提供者,因为AppModule不会导出其提供者。
  • 你也不应该加载你的整个AppModule来测试LoginComponent
  • 您将不得不模拟这些提供商,因为它们看起来像是在进行网络呼叫。

代码示例:

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

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.