'Cannot read properties of undefined (reading 'subscribe') in Unit Test NgOnInIt

I tried a lot of SO Question's answers but nothing worked for this.so in mt test im doing something like this.

const stubStudentService = jasmine.createSpyObj('StudentsCrudService',['getAllStudents','updateStudent']);
const stubWebSocketService = jasmine.createSpyObj('WebsocketService',['getNotified']);

describe('StudentsListComponent', () => {
  let component: StudentsListComponent;
  let fixture: ComponentFixture<StudentsListComponent>;;
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [StudentsListComponent],
      imports: [],
      providers: [
        { provide: StudentsCrudService, useValue: stubStudentService },
        { provide: WebsocketService, useValue: stubWebSocketService },
        NotificationService,
      ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(StudentsListComponent);
    stubStudentService.getAllStudents.and.returnValue(of(studentPayload));
    stubWebSocketService.getNotified.and.returnValue(of('success'));
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

In my component, it look like this

  constructor(
    private studentService: StudentsCrudService,
    private notificationService: NotificationService,
    private webSocketNotifier: WebsocketService
  ) {}

  ngOnInit(): void {
    this.studentSubscription();
    this.webSocketSubscription();
  }

  studentSubscription() {
    this.studentQueryRef =  this.studentService
    .getAllStudents()
    this.initSubscription.add(
      this.studentQueryRef
        .valueChanges.subscribe((response) => {
          this.paginatedStudents = {...response.data.paginateStudents}
        })
    );
  }

When I run the test im getting Cannot read properties of undefined (reading 'subscribe') at StudentsListComponent.studentSubscription. I tried so many things but nothing worked.



Solution 1:[1]

The first fixture.detectChanges is when ngOnInit is called.

You have mocked studentService correctly but you haven't mocked the return of getAllStudents incorrectly.

Try this (follow comments with !!):

const stubStudentService = jasmine.createSpyObj('StudentsCrudService',['getAllStudents','updateStudent']);
const stubWebSocketService = jasmine.createSpyObj('WebsocketService',['getNotified']);

describe('StudentsListComponent', () => {
  let component: StudentsListComponent;
  let fixture: ComponentFixture<StudentsListComponent>;
  // !! make the following changes
  let stubStudentService: jasmine.SpyObj<StudentCrudService>;
  let stubWebSocketService: jasmine.SpyObj<WebsocketService>;
  
  beforeEach(async () => {
    // !! assign the spies in a beforeEach so they are fresh for every test
    stubStudentService = jasmine.createSpyObj('StudentsCrudService', 
      ['getAllStudents','updateStudent']);
    stubWebSocketService = jasmine.createSpyObj('WebsocketService', 
    ['getNotified']);

    await TestBed.configureTestingModule({
      declarations: [StudentsListComponent],
      imports: [],
      providers: [
        { provide: StudentsCrudService, useValue: stubStudentService },
        { provide: WebsocketService, useValue: stubWebSocketService },
        NotificationService,
      ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(StudentsListComponent);
    // !! change below to return object of valueChanges
    stubStudentService.getAllStudents.and.returnValue({ valueChanges: of(studentPayload) });
    stubWebSocketService.getNotified.and.returnValue(of('success'));
    component = fixture.componentInstance;
    // !! the below fixture.detectChanges will call ngOnInit
    fixture.detectChanges();
  });

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

The above should hopefully fix your problem.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AliF50