I've got this login component code snippet that I need help testing in Angular.
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { BasicAuthService } from './../../services/auth/basic-auth.service';
import {ConfigService} from '../../services/common/config.service';
import { RefdataService } from '../../services/common/refdata.service';
import { config } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { RouteGuardService } from '../../services/auth/route-guard.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
form: FormGroup;
private formSubmitAttempt: boolean;
invalidLogin = false;
credentials:any;
userPermissions: any;
errorMessage: any = null;
isLoading: boolean = false;
constructor(
private router: Router,
private fb: FormBuilder,
private basicAuthService: BasicAuthService,
public config: ConfigService,
private refdataService: RefdataService,
private authGuard: RouteGuardService,
) { }
ngOnInit(): void {
this.form = this.fb.group({
userName: ['', Validators.required],
password: ['', Validators.required]
});
}
handleAuthentication() {
if (this.form.valid) {
this.isLoading = true;
console.log("handleAuthentication");
let iUserName = this.form.value.userName;
let iPassword = this.form.value.password;
this.credentials = {
username: iUserName,
password: iPassword
}
this.basicAuthService.getAuthentication(this.credentials)
.pipe(
switchMap(
data => {
console.log(data);
this.invalidLogin = false;
this.formSubmitAttempt = true;
return this.refdataService.loadRefDataConfig();
})
).subscribe(
res => {
// some variable updates
this.router.navigate(['main']);
},
error => {
this.isLoading = false;
console.log(error.status);
let mess = '';
if (error.status === 401) {
mess = 'Invalid Login credentials supplied! Correct the errors and re-submit.'
} else {
mess = error.error
}
this.errorMessage = { _body: 'Error Code: ' + error.status + '\nMessage: ' + mess };
this.errorService.openSnackBar(this.errorMessage, 'Close', 'red-snackbar', 10000);
this.invalidLogin = true;
console.log(this.invalidLogin);
}
);
}
}
}
I want to write a test for this component and mock all services. Can someone assist me with this as I am new to Angular?
Below is my current failing test:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms'
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
ReactiveFormsModule,
FormsModule,
HttpClientTestingModule
],
declarations: [ LoginComponent ],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Error:
LoginComponent > should create
TypeError: Cannot read property 'environmentName' of undefined
at <Jasmine>
at new BasicAuthService (http://localhost:0000/_karma_webpack_/src/app/services/auth/basic-auth.service.ts:24:49)
at Object.BasicAuthService_Factory [as factory] (ng:///BasicAuthService/ɵfac.js:5:10)
at R3Injector.hydrate (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:11248:1)
at R3Injector.get (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:11070:1)
at NgModuleRef$1.get (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:24198:1)
at Object.get (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:22101:1)
at getOrCreateInjectable (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:3921:1)
at ɵɵdirectiveInject (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:13752:1)
at NodeInjectorFactory.LoginComponent_Factory [as factory] (ng:///LoginComponent/ɵfac.js:6:50)
at getNodeInjectable (http://localhost:0000/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:4029:1)
Expected undefined to be truthy.
Error: Expected undefined to be truthy.
at <Jasmine>
at UserContext.<anonymous> (http://localhost:0000/_karma_webpack_/src/app/components/login/login.component.spec.ts:35:23)
at ZoneDelegate.invoke (http://localhost:0000/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:364:1)
at ProxyZoneSpec.onInvoke (http://localhost:0000/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:292:1)
The failure points to an issue with the constructor for the basic-auth-service.
export class BasicAuthService {
environmentName = '';
environmentUrl = '';
constructor(
private http: HttpClient,
private config: ConfigService,
private runtimeConfig: RuntimeConfigService,
) {
this.environmentName = runtimeConfig.config.environmentName;
this.environmentUrl = this.environmentName == "localhost" ? "http://" + runtimeConfig.config.serviceUrl : runtimeConfig.config.serviceUrl;
}
I need to know how to mock this service (and any other called services) to prevent its constructor from running. How can I create a simple mock of BasicAuthService for my component test?