It doesn't work because the changeDetectorRef in your fixture isn't the same as in your component. Taken from the issue in Angular:
"...changeDetectorRef on a ComponentRef points to the change detector of the root (host) view of a dynamically created component. Then, inside the host view we've got the actual component view, but the component view is OnPush thus we never refresh it!" - source
Option A. One way to solve this is to use the components injector to get the real changeDetectionRef:
describe('MyComponent', () => {
let fixture;
let component;
beforeEach(() => {
TestBed.configureTestingModule({ ... }).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('does something', () => {
// set the property here
component.property = 'something';
// do a change detection on the real changeDetectionRef
fixture.componentRef.injector.get(ChangeDetectorRef).detectChanges();
expect(...).toBe(...);
});
});
You could also just use the initial binding to an @Input (which initially triggers changedetection for an OnPush strategy):
Option B1:
describe('MyComponent', () => {
let fixture;
let component;
beforeEach(() => {
TestBed.configureTestingModule({ ... }).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
it('does something', () => {
// set the property here
component.property = 'something';
// do the first (and only) change detection here
fixture.detectChanges();
expect(...).toBe(...);
});
});
or for example:
Option B2:
describe('MyComponent', () => {
let fixture;
let component;
it('does something', () => {
// set the property here
setup({ property: 'something' });
expect(...).toBe(...);
});
function setup(props: { property? } = {}) {
TestBed.configureTestingModule({ ... }).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
Object.getOwnPropertyNames(props).forEach((propertyName) => {
component[propertyName] = props[propertyName];
});
// do the first (and only) change detection here
fixture.detectChanges();
}
});