Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
267 views
in Technique[技术] by (71.8m points)

typescript - "undefined is not an object" when running Karma tests, no error in actual execution

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);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...