ngOnChanges not called in Angular 4 unit test detectChanges() ngOnChanges not called in Angular 4 unit test detectChanges() angular angular

ngOnChanges not called in Angular 4 unit test detectChanges()


The short answer to this question is that ngOnChanges doesn't get fired automatically during unit tests so I had to call it manually.

  it('should be disabled when passed a single promise', async () => {    let promise;    let resolve;    // should not be disabled here    expect(buttonElement.disabled).toBe(false);    // Pass a promise to the component to disable it    promise = new Promise(r => resolve = r);    component.ngOnChanges({      promise: new SimpleChange(null, promise, null)    });    fixture.detectChanges();    expect(buttonElement.disabled).toBe(true);    // now resolve the promise and make sure it's enabled again.    promise.then(() => {      fixture.detectChanges();      expect(buttonElement.disabled).toBe(false);    });    resolve();  });


Have you tried asserting before adding that promise?

it('should be disabled when passed a single promise', async(() => {  let promise;  // should not be disabledhere  expect(buttonElement.disabled).toBe(false);  let resolve;  const promise = new Promise(r => resolve = r);  component.promise = promise;  component.ngOnChanges(); // Call this here, TestBed doesn't know it needs to.  fixture.detectChanges();  expect(buttonElement.disabled).toBe(true);  // now resolve the promise and make sure it's disabled again.  resolve();  fixture.detectChanges();  expect(buttonElement.disabled).toBe(false);}));

Edit: As noted in the comments, the way you set that promise property doesn't work with TestBed, so it never calls your ngOnChanges() method. You could call it directly, like I did above.

Alternatively, wrap your test component in a host component:

@Component({  selector: 'test-component',  template: `<my-component [promise]="promise"></my-component>`})class TestComponent {  promise;}// then use that in your test instead:const wrapperCmp = TestBed.createComponent(TestComponent);wrapperCmp.promise = promise; // and check for the button state before and after all the changes.