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.