until-destroy: Calling ngOnDestroy on test does not complete subscription

"@angular/core": "9.0.2",
"rxjs": "6.5.4",
"@ngneat/until-destroy": "7.1.1",
"jasmine-core": "3.5.0",

On a component defined as

@UntilDestroy()
@Component({
  templateUrl: 'none-improvement.html',
  selector: 'cv-none-improvement-page',
  styleUrls: ['none-improvement.scss']
})
export class NoneImprovementPageComponent implements OnInit, OnDestroy {
  public firstName: string;

  constructor(
    private _user: UserProfileStore,
  ) {
  }

  public ngOnInit() {
    this._user.profile$
      .pipe(
        untilDestroyed(this)
      )
      .subscribe(u => this.firstName = u.get('firstName'));
  }

  public ngOnDestroy() {
    //
  }
}

I write this test:

  it('stops getting first name from user profile after destroy', () => {
    expect(sut.firstName).toBeUndefined();
    sut.ngOnInit();
    mockUserProfileStore.profileSubject$.next(new UserProfile(<any>{ firstName: 'testName' }).toImmutable());
    expect(sut.firstName).toEqual('testName');
    sut.ngOnDestroy();
    mockUserProfileStore.profileSubject$.next(new UserProfile(<any>{ firstName: 'newName' }).toImmutable());
    expect(sut.firstName).toEqual('testName');
  });

which fails. But if I use untilDestroyed(this, 'ngOnDestroy') passes. Is ngOnDestroy not the default method that triggers the unsubscription?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (3 by maintainers)

Most upvoted comments

I tested, it works for me… If you don’t provide any reproduction then I see no reason to continue the dialogue, because it’s like “shooting a stone”. 😉

Well, as many other teams, we are testing many components (those that have no need to test UI) in unit tests without using Testbed. The component is instantiated manually using new and triggering the lifecycles hooks on demand. The component does have ngOnDestroy defined.

What would be the reason to invoke life cycle hooks manually? 🕵

  1. you’ve got a ComponentFixture with detectChanges and destroy methods that manages this stuff
  2. we don’t patch ngOnDestroy method on prototypes. You have to create a ComponentFixture and manage it via its methods. The view information is stored in the component definition static property on the component class (with on destroy listener).