Reputation: 3842
I'm not much familiar with Angular Unit testing. I have been working on this issue for almost a day. Please tell me why this coming and how to solve this issue? There are more issues similar to this one.
I already referred to this one, which is not helped. Angular testing Cannot read property 'name' of undefined
I found that the error is occurring inside the
addRole
function inadd-role.component.ts
.
Error
TypeError: Cannot read property 'roleName' of undefined
at AddRoleComponent_Template (ng:///AddRoleComponent.js:59:52)
at executeTemplate (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9545:1)
at refreshView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9414:1)
at refreshComponent (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10580:1)
at refreshChildComponents (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9211:1)
at refreshView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9464:1)
at renderComponentOrTemplate (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9528:1)
at tickRootContext (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10754:1)
at detectChangesInRootView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10779:1)
at RootViewRef.detectChanges (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:22792:1)
TypeError: Cannot read property 'roleName' of undefined
at AddRoleComponent.addRole (src/app/components/admin/add-role/add-role.component.ts:53:29)
at <Jasmine>
at UserContext.<anonymous> (src/app/components/admin/add-role/add-role.component.spec.ts:60:17)
at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:364:1)
at ProxyZoneSpec.push.QpwO.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:292:1)
at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:363:1)
Here are the lines that the errors are coming,
add-role.component.ts:53 -> const claimValue = role.roleName;
add-role.component.spec.ts:60 -> component.addRole();
add-role.component.ts
import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router';
import {IRole} from 'src/app/models/role.model';
import {AlertService} from 'src/app/services/alert-service/alert-service.service';
import {AuthService} from 'src/app/services/auth/auth.service';
import {ClaimsService} from 'src/app/services/claims/claims.service';
@Component({
selector: 'app-add-role',
templateUrl: './add-role.component.html',
styleUrls: ['./add-role.component.scss']
})
export class AddRoleComponent implements OnInit {
addRoleForm: FormGroup;
roleName?: string;
role?: IRole;
constructor(
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private router: Router,
private formBuilder: FormBuilder,
private claimService: ClaimsService,
private alertService: AlertService
) {
this.buildForm();
}
get formControls() {
return this.addRoleForm.controls;
}
onDataLoadFailed(errors: any): void {
}
onDataLoadSuccessful(results: any): void {
this.role = results;
}
ngOnInit(): void {
}
addRole() {
const role = this.addRoleForm.value;
const claimValue = role.roleName;
this.claimService.addRole(claimValue).subscribe(
data => this.onSuccess(data),
error => this.handleError(error),
() => this.onComplete()
);
}
onSuccess(data): void {
this.alertService.success(data.key, data.message);
}
handleError(errors): void {
this.alertService.errors(errors);
}
onComplete(): void {
}
private buildForm() {
this.addRoleForm = this.formBuilder.group({
roleName: ['', [Validators.required]],
});
}
}
add-role.component.spec.ts
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {NO_ERRORS_SCHEMA} from '@angular/core';
import {FormBuilder} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router';
import {AlertService} from 'src/app/services/alert-service/alert-service.service';
import {AuthService} from 'src/app/services/auth/auth.service';
import {ClaimsService} from 'src/app/services/claims/claims.service';
import {AddRoleComponent} from './add-role.component';
describe('AddRoleComponent', () => {
let component: AddRoleComponent;
let fixture: ComponentFixture<AddRoleComponent>;
beforeEach(() => {
const formBuilderStub = () => ({group: object => ({})});
const activatedRouteStub = () => ({});
const routerStub = () => ({});
const alertServiceStub = () => ({
success: (key, message) => ({}),
errors: errors => ({})
});
const authServiceStub = () => ({});
const claimsServiceStub = () => ({
addRole: claimValue => ({subscribe: f => f({})})
});
TestBed.configureTestingModule({
schemas: [NO_ERRORS_SCHEMA],
declarations: [AddRoleComponent],
providers: [
{provide: FormBuilder, useFactory: formBuilderStub},
{provide: ActivatedRoute, useFactory: activatedRouteStub},
{provide: Router, useFactory: routerStub},
{provide: AlertService, useFactory: alertServiceStub},
{provide: AuthService, useFactory: authServiceStub},
{provide: ClaimsService, useFactory: claimsServiceStub}
]
});
fixture = TestBed.createComponent(AddRoleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
afterEach(() => {
fixture.destroy();
});
it('can load instance', () => {
expect(component).toBeTruthy();
});
describe('addRole', () => {
it('makes expected calls', () => {
const claimsServiceStub: ClaimsService = fixture.debugElement.injector.get(
ClaimsService
);
spyOn(component, 'onSuccess').and.callThrough();
spyOn(component, 'handleError').and.callThrough();
spyOn(component, 'onComplete').and.callThrough();
spyOn(component, 'addRole').and.callThrough();
component.addRole();
expect(component.onSuccess).toHaveBeenCalled();
expect(component.handleError).toHaveBeenCalled();
expect(component.onComplete).toHaveBeenCalled();
expect(component.addRole).toHaveBeenCalled();
});
});
});
Upvotes: 0
Views: 2928
Reputation: 93
If it is about a property of an object which is used in an html template, make sure to check for undefined...
e.g. <some-component *ngIf="someObject.property === somevalue"
.. make sure to check the object is defined, like this: <some-component *ngIf="someObject?.property === somevalue"
.
Upvotes: 0
Reputation: 713
addRole() {
const role = this.addRoleForm.value; <---- this line creating issue
const claimValue = role.roleName;
this.claimService.addRole(claimValue).subscribe(
data => this.onSuccess(data),
error => this.handleError(error),
() => this.onComplete()
);
}
to fixed that you need to do this -->
let component: AddRoleComponent;
let fixture: ComponentFixture<AddRoleComponent>;
beforeEach(() => {
const formBuilderStub = () => ({group: object => ({})});
const activatedRouteStub = () => ({});
const routerStub = () => ({});
const alertServiceStub = () => ({
success: (key, message) => ({}),
errors: errors => ({})
});
const authServiceStub = () => ({});
const claimsServiceStub = () => ({
addRole: claimValue => ({subscribe: f => f({})})
});
TestBed.configureTestingModule({
schemas: [NO_ERRORS_SCHEMA],
declarations: [AddRoleComponent],
providers: [
{provide: FormBuilder, useFactory: formBuilderStub},
{provide: ActivatedRoute, useFactory: activatedRouteStub},
{provide: Router, useFactory: routerStub},
{provide: AlertService, useFactory: alertServiceStub},
{provide: AuthService, useFactory: authServiceStub},
{provide: ClaimsService, useFactory: claimsServiceStub}
]
});
fixture = TestBed.createComponent(AddRoleComponent);
component = fixture.componentInstance;
// newly added line
component.addRoleForm = component.formBuilder.group({
roleName: ['', [Validators.required]],
});
fixture.detectChanges();
});
please check the line after "newly added line" comment
Upvotes: 1