Home > Enterprise >  Karma: TypeError: Cannot read properties of undefined (reading 'subscribe')
Karma: TypeError: Cannot read properties of undefined (reading 'subscribe')

Time:03-30

I am trying to test a method (refreshMemberList()) that contains a subscribe, but when I run the tests I get this error from Karma. Can anyone tell me what is going on? Thank you very much in advance, such a great community you are :D

Jasmine spec list failure:

    MemberListComponent > refreshMemberList refreshes members list
TypeError: Cannot read properties of undefined (reading 'subscribe')

member-list.component.ts:

describe('MemberListComponent', () => {
  let component: MemberListComponent;
  let fixture: ComponentFixture<MemberListComponent>;
  let mockMemberListService: jasmine.SpyObj<MemberListService>;
  let modalService: NgbModal;

  beforeEach(async () => {
    mockMemberListService = jasmine.createSpyObj(['getMembers']);
    mockMemberListService.getMembers.and.returnValue(memberMockObject.fakeMemberListJSON);
    await TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        {
          provide: MemberListService,
          useValue: mockMemberListService,
        }
      ],
      declarations: [MemberListComponent],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(MemberListComponent);
    component = fixture.componentInstance;
    modalService = TestBed.get(NgbModal);
  });

  it('refreshMemberList refreshes members list', () => {
    component.refreshMemberList(memberMockObject.dataMemberMap);
    fixture.detectChanges();
    expect(component.members).toEqual(memberMockObject.fakeMembers);
  });


});

member-list.component.ts:

export class MemberListComponent implements OnInit {
  public title: String = "Members";
  public showMemberDeletedAlert: Boolean;
  private _memberListService: MemberListService;
  public members: Member[] = []; 
  private dataMemberMap: Map<string, string>;
  public page: number = 0;
  public pageSize: number = 10;
  public collectionSize: number;
  public isLoading: boolean = true;

  constructor(
    memberListService: MemberListService,
    private _modalService: NgbModal
  ) {
    this._memberListService = memberListService;
  }

  ngOnInit(): void {
    if(history.state.type==="delete")
      this.showDeletedAlert()
    this.dataMemberMap =  new Map([
      ["name", ""],
      ["role", ""],
      ["skill", ""],
      ["skillLevel", ""],
      ["language", ""],
      ["languageLevel", ""]
      ]);
    this.retrieveMemberList();
  }

  retrieveMemberList(): void {
    this.isLoading = true;
    this._memberListService.getMembers(this.dataMemberMap!, this.page, this.pageSize).subscribe((data) => {
      this.members = data.memberList;
      this.collectionSize = data.totalPages * this.pageSize;
      this.isLoading = false;
    });
  }

  refreshMemberList(dataMemberMap: Map<string, string>): void {
    this.dataMemberMap = dataMemberMap;
    this.retrieveMemberList();
  }

}

CodePudding user response:

It is undefined, so can't read the subscribe property, since you want this (_memberListService) to be private, you can just use (memberListService) on the constructor as private and do not use _memberListService, it'd something like

  constructor(
    private memberListService: MemberListService,
    private _modalService: NgbModal
  ) {}

and when you call getMembers you can just use this.memberListService.getMembers(...

CodePudding user response:

Why do you have a class property of type MemberListService? Just use the dependency injection as

constructor(private memberListService: MemberListService) {} 

Then just use it as:

...
this.memberListService.getMembers(...);

Also, you have all this logic been triggered right from the beginning, in your ngOnInit lifecycle hook, which is fine; the first test you should have for this component should be this one:

it('should create', () => {
    expect(component).toBeTruthy();
});

This test (which is the first test by default) verifies the successful creation of your component, so any logic within your ngOnInit will be tested, some of this logic is calling your getMembers service function sending 3 parameters, maybe some or all of those are undefined?

Also, I don't know what memberMockObject is in your test file, so for setting the return type, I would say use of from rxjs to create an observable:

mockMemberListService.getMembers
  .and.returnValue(of(yourDesiredValueHere));
  • Related