I'm trying to add unit tests for a skeleton project. The existing component/service works fine, but throws the above error when testing.
Component
export class ObjectivesComponent implements OnInit, OnDestroy {
accessoryGroups: AccessoryGroup[];
objectives: Objective[];
constructor(private accessoryGroupService: AccessoryGroupService, private objectivesService: ObjectivesService) {}
ngOnInit() {
this.accessoryGroupService.getAccessoryGroups().subscribe(result => {
this.accessoryGroups = result;
console.log('retrieved ' + result.length + ' accessory groups');
}, error => console.error(error));
this.objectivesService.getObjectives().subscribe(result => {
this.objectives = result.map(x => {
const group = this.accessoryGroups.find(y => y.id === x.accessoryGroupId);
const objective = x;
objective.accessoryGroupName = group.name;
return objective;
});
console.log('retrieved ' + result.length + ' objectives');
}, error => console.error(error));
}
Each of the services is a simple http call:
export class ObjectivesService {
constructor(public http: HttpClient) {
getObjectives(): Observable<Objective[]> {
return this.http.get<Objective[]>('objectives');
}
And the component test replaces the http calls with mocked results
describe('ObjectivesComponent', () => {
let component: ObjectivesComponent;
let fixture: ComponentFixture<ObjectivesComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [ ObjectivesComponent ],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: HttpRequestInterceptorMock, multi: true},
MessageService, ConfirmationService
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ObjectivesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
But running the tests results in:
TypeError: undefined is not an object (evaluating 'group.name')
I can verify that the following line is the issue by replacing group.name with a literal string:
objective.accessoryGroupName = group.name;
I have passing tests for the two services that verify the results. Not sure if this has something to do with mapping from one Observable array to another or the fact that it's a couple of levels deep in terms of arrow functions.
For completeness, the HttpRequestInterceptor is:
export class HttpRequestInterceptorMock implements HttpInterceptor {
constructor(private injector: Injector) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url) {
return next.handle(request);
}
if (request.url.indexOf('objectives') > -1) {
return of(new HttpResponse({ status: 200, body: mockObjectives }));
} else if (request.url.indexOf('accessorygroups') > -1) {
return of(new HttpResponse({ status: 200, body: mockAccessoryGroups }));
} else if (request.url.indexOf('franchises') > -1) {
return of(new HttpResponse({ status: 200, body: mockFranchises }));
}
return next.handle(request);
}
}