I'm trying to write a Jasmine Unit Test (with Karma) for an Angular component that uses two services and one form. The tutorials on testing (like this one from the Angular Docs) show only how to test a component with one service and somehow I can't make it work with a bit more complex component:
My component: user-login.component.ts:
The component has a login form, where the user can put in his credentials. OnSubmit
I send the provided credentials to an Authentication Service, which handles the http request to my API. If the http response from the API has status 200 it will contain a login token (JWT), which I store with another service that I called 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")
}
}
});
}
}
My test: user-login.component.spec.ts:
So I understood that the three things I provide in the constructor (FormBuilder
, TokenStorageService
and AuthenticationService
) I also have to provide in my TestBed
. And since I don't really want to inject the services for the Unit test I'm using Stub Services instead. So I did this:
TestBed.configureTestingModule({
imports: [{HttpClientTestingModule}],
providers: [{provide: FormBuilder}, { provide: TokenStorageService, useValue: tokenStorageServiceStub }, { provide: AuthenticationService, useValue: authenticationServiceStub }
The whole test then looks like this:
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();
});
});
I commented 4 lines out since I think they are wrong, but in the the Angular Docs example they are also injecting the real services, even tough they say they don't want to use the real services in the test. I don't understand that part in the Docs example?
But either way I keep getting this Error message:
Since the error says something about @NgModule
I think it may has to do with my app.module.ts
file? Here is my 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 { }
from Angular Unit Testing with Jasmine - Error: Please add an @NgModule annotation
No comments:
Post a Comment