在Angular中的onInit()内编写订阅的单元测试

在Angular中的onInit()内编写订阅的单元测试,angular,unit-testing,karma-jasmine,Angular,Unit Testing,Karma Jasmine,我有一个微调器组件类,如下所示,它将显示/隐藏使用角度材质的进度微调器 export class SpinnerComponent implements OnInit, OnDestroy { visible = true; private subscription: Subscription; constructor(private spinnerService: SpinnerService) {} ngOnInit() { this.s

我有一个微调器组件类,如下所示,它将显示/隐藏使用角度材质的进度微调器

export class SpinnerComponent implements OnInit, OnDestroy {
    visible = true;
    private subscription: Subscription;

    constructor(private spinnerService: SpinnerService) {}

    ngOnInit() {
         this.subscription = this.spinnerService.spinnerState.subscribe((state: SpinnerState) => {
                this.visible = state.show;
           });
     }
    ngOnDestroy() {
         if (this.subscription) {
            this.subscription.unsubscribe();
         }
    }
}
我如何编写一个规范来测试ngOnInit()方法中下面所示的特定行

this.visible = state.show;

第一个解决方案:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SpinnerComponent } from './spinner.component';
import { of } from 'rxjs/observable/of';

describe('SpinnerComponent', () => {
  let component: SpinnerComponent;
  let fixture: ComponentFixture<SpinnerComponent>;
  const fakeSpinner = {
    spinnerState: of({ show: false }),
  };

  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [SpinnerComponent],
        providers: [{ provide: SpinnerService, useValue: fakeSpinner }],
      }).compileComponents();
    }),
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(SpinnerComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should set component.visible based on spinnerService state', () => {
    expect(component.visible).toEqual(false)
  });
});

如果你能回答的话,我还有一个问题,所以我在订阅者中设置了超时,它也在ngoninitsettimeout(()=>{document.querySelector(entityIdentifier.classList.remove('highlight');},2000)中设置了超时;所以在这种情况下可以做什么>感谢这个答案,但是我无法理解在第二个场景中为什么fixture.detectChanges不起作用?我搔了好几个小时才无意中听到你的回答。我订阅我的主题,然后用done()将期望放在其中;最后。这适用于component.ngOnInit,但不适用于fixture.detectChanges,知道为什么吗?
class FakeSpinnerService {
  private spinnerStateSource = new Subject();
  spinnerState = this.spinnerStateSource.asObservable();

  emit(val: boolean) {
    this.spinnerStateSource.next({ show: val });
  }
}

it('should set component.visible based on spinnerService state', () => {
  const fakeService = new FakeSpinnerService();
  const component = new SpinnerComponent(fakeService as any);

  // initial value
  expect(component.visible).toBe(true);

  component.ngOnInit();

  fakeService.emit(false);
  expect(component.visible).toBe(false);

  fakeService.emit(true);
  expect(component.visible).toBe(true);
});