使用 Jasmine 进行 Angular 单元测试 - 错误 : Please add an @NgModule annotation

标签 angular unit-testing jasmine karma-jasmine

我正在尝试为使用两种服务和一种形式的 Angular 组件编写 Jasmine 单元测试(使用 Karma)。测试教程 ( like this one from the Angular Docs ) 仅展示了如何使用一项服务测试组件,而我无法以某种方式让它与更复杂的组件一起工作:

我的组件:user-login.component.ts:

该组件有一个登录表单,用户可以在其中输入他的凭据。 OnSubmit 我将提供的凭据发送到身份验证服务,该服务处理对我的 API 的 http 请求。如果来自 API 的 http 响应状态为 200,它将包含一个登录 token (JWT),我将其存储在另一个名为 TokenStorageService 的服务中:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { TokenStorageService } from '../../../_services/token-storage.service';
import { AuthenticationService } from '../../../_services/authentication.service';
import { AuthRequest } from '../../../_models/authRequest';

@Component({
  selector: 'app-user-login',
  templateUrl: './user-login.component.html',
  styleUrls: ['./user-login.component.scss']
})
export class UserLoginComponent implements OnInit {

  loginForm: FormGroup;

  constructor(private formBuilder: FormBuilder,
    private tokenStorage: TokenStorageService,
    private authService: AuthenticationService) { }

   ngOnInit() {
     this.loginForm = this.formBuilder.group({
       username: ['', Validators.compose([Validators.required])],
       password: ['', Validators.required]
     });
   }

  onSubmit() {
    this.authService.login({ 
      userName: this.loginForm.controls.username.value, 
      password: this.loginForm.controls.password.value
    })
    .subscribe(data => {  
      if (data.status === 200) {
        this.tokenStorage.saveToken(data.body)
        console.log("SUCCESS: logged in")
      } 
    }
    });
  }
}

我的测试:user-login.component.spec.ts:

所以我明白我在构造函数中提供的三个东西(FormBuilderTokenStorageServiceAuthenticationService)我也必须在我的测试床。因为我真的不想为单元测试注入(inject)服务,所以我改用 stub 服务。所以我这样做了:

TestBed.configureTestingModule({
      imports: [{HttpClientTestingModule}],
      providers: [{provide: FormBuilder}, { provide: TokenStorageService, useValue: tokenStorageServiceStub }, { provide: AuthenticationService, useValue: authenticationServiceStub }

整个测试看起来像这样:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserLoginComponent } from './user-login.component';
import { FormBuilder } from '@angular/forms';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TokenStorageService } from 'src/app/_services/token-storage.service';
import { AuthenticationService } from 'src/app/_services/authentication.service';

describe('UserLoginComponent', () => {
  let component: UserLoginComponent;
  let fixture: ComponentFixture<UserLoginComponent>;
  let tokenStorageServiceStub: Partial<TokenStorageService>;
  let authenticationServiceStub: Partial<AuthenticationService>;
  // let tokenStorageService;
  // let authenticationService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [{HttpClientTestingModule}],
      providers: [{provide: FormBuilder}, { provide: TokenStorageService, useValue: tokenStorageServiceStub }, { provide: AuthenticationService, useValue: authenticationServiceStub } ],
      declarations: [ UserLoginComponent ]
    })
    fixture = TestBed.createComponent(UserLoginComponent);
    component = fixture.componentInstance;
    // tokenStorageService = TestBed.inject(TokenStorageService);
    // authenticationService = TestBed.inject(AuthenticationService);
    fixture.detectChanges();
  });

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

我评论了 4 行,因为我认为它们是错误的,但在 the Angular Docs example 中他们也在注入(inject)真正的服务,即使他们说他们不想在测试中使用真正的服务。我不明白文档示例中的那部分内容?

但无论哪种方式,我都会不断收到此错误消息:

enter image description here

由于错误说明了一些关于 @NgModule 的信息,我认为这可能与我的 app.module.ts 文件有关?这是我的 app.module.ts:

@NgModule({
 declarations: [
   AppComponent,
   SidebarComponent,
   UsersComponent,
   DetailsComponent,
   ProductsComponent,
   UploadFileComponent,
   GoogleMapsComponent,
   AddUserComponent,
   ProductFormComponent,
   UserLoginComponent,
   EditUserComponent,
   ProductDetailsComponent,
   MessagesComponent,
   MessageDetailsComponent,
   ChatComponent,
   UploadMultipleFilesComponent,
   InfoWindowProductOverviewComponent,
   AddDormComponent,
   AddProductComponent
 ],
 imports: [
   BrowserModule,
   AppRoutingModule,
   HttpClientModule, 
   BrowserAnimationsModule,
   FormsModule,
   ReactiveFormsModule,
   ImageCropperModule,
   DeferLoadModule,
   //Angular Material inputs (spezielle UI Elemente)
   MatDatepickerModule,
   MatInputModule,
   MatNativeDateModule,
   MatSliderModule,
   MatSnackBarModule,
   MatSelectModule,
   MatCardModule,
   MatTooltipModule,
   MatChipsModule,
   MatIconModule,
   MatExpansionModule,
   MDBBootstrapModule,
   AgmCoreModule.forRoot({
     apiKey: gmaps_environment.GMAPS_API_KEY 
   })
  ],
  providers: [
   UploadFileService, 
   {provide: MAT_DATE_LOCALE, useValue: 'de-DE'},   
   {provide:HTTP_INTERCEPTORS, useClass:BasicAuthHttpInterceptorService, multi:true},
 ],   
 bootstrap: [AppComponent],
})
export class AppModule { }

最佳答案

现在您只声明了 stub tokenStorageServiceStubauthenticationServiceStub,但是您需要在提供它们之前对其进行初始化。沿着这些线的东西:

tokenStorageServiceStub = {
  saveToken: () => {}
};


authenticationServiceStub = {
  login: () => of({status: 200, body: {}})
}

此外,请考虑@PrincelsNinja 的建议。

关于使用 Jasmine 进行 Angular 单元测试 - 错误 : Please add an @NgModule annotation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63533754/

相关文章:

angular - 如何绑定(bind)到 angular2 中投影内容中的属性?

C# 单元测试 : Testing a method that uses MapPath

unit-testing - 如何对 Go Gin 处理程序函数进行单元测试?

vue.js - 如何用 Jest + Vuejs 模拟 window.location.href?

javascript - 有没有办法在自定义匹配器中使用 Jasmine 默认匹配器?

javascript - Amplify.service.api.get 返回sampleCloudAPI 不存在

angular - AngularCompilerPlugin : Forked Type Checker exited unexpectedly 中的警告

angular - 等同于 RxJs 中的发布主题

c# - 测试时的努力问题

javascript - Protractor :如何获取当前的浏览器宽度?