【问题标题】:Writing unit test for subscription inside onInit() in Angular在 Angular 的 onInit() 中为订阅编写单元测试
【发布时间】:2018-09-06 03:44:49
【问题描述】:

我有一个如下所示的 Spinner 组件类,它将使用 Angular 材料显示/隐藏 Progress Spinner。

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;

【问题讨论】:

    标签: angular unit-testing karma-jasmine


    【解决方案1】:

    第一个解决方案:

    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)
      });
    });
    

    需要注意的重要一点是,我们提供的是 spinner 服务的模拟实现。

    第二种解决方案:

    另一种测试方法是创建一个浅层测试,根本不使用 Angular 测试实用程序。由于您不关心模板交互,因此您也可以像测试常规 ts 类一样对其进行测试。

    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);
    });
    

    【讨论】:

    • 我还有一个问题,如果你能回答,所以我在订阅者内部设置了超时,也在 ngOninit setTimeout(() => { document.querySelector(entityIdentifier).classList.remove ('高亮'); }, 2000);那么在这种情况下可以做什么>
    • 感谢您的回答,但是在第二种情况下我无法理解为什么 fixture.detectChanges 不起作用?在偶然发现你的答案之前,我一直在挠头。我订阅了我的主题,然后使用 done() 将期望放入其中;在末尾。这适用于component.ngOnInit,但不适用于fixture.detectChanges,知道为什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2022-01-01
    • 2021-06-28
    • 2018-10-03
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多