angular - 单元测试主题 : Cannot read property 'unsubscribe' of undefined

标签 angular unit-testing rxjs observable subject

在我向服务添加主题并在组件中订阅它后,该组件的所有测试都失败并显示

Cannot read property 'unsubscribe' of undefined

我想知道
- 为什么此组件的所有测试都失败并且
- 如何测试一个Subject、它的next()方法和它的订阅,就像下面在Angular 8中一样。

组件:

export class TrackerComponent implements OnInit, OnDestroy {
  trackSubscription: Subscription;

  constructor(private trackerService: TrackerService) { }

  ngOnInit() {
    this.trackSubscription = this.trackerService.trackSubject.subscribe((state) => {
      console.log(state);
    });
  }

  startTracking() { // called by clicking html button
    this.trackerService.start();
  }

  ngOnDestroy() {
    this.trackSubscription.unsubscribe();
  }
}

服务:

export class TrackerService {
   trackSubject = new Subject<boolean>();

   start() {
       // do stuff
       this.trackSubject.next(true);
   }
}

测试:

describe('TrackerComponent', () => {
  let component: TrackerComponent;
  let fixture: ComponentFixture<TrackerComponent>;
  let trackerService: jasmine.SpyObj<TrackerService>;

  // helper function
  const el = (selector) => fixture.nativeElement.querySelector(selector);

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [TrackerComponent],
      providers: [
        { provide: TrackerService, useFactory: () => spyOnClass(TrackerService) }
      ]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TrackerComponent);
    component = fixture.componentInstance;
    trackerService = TestBed.get(TrackerService);
    fixture.detectChanges();
  });


  // it should show a start button
  it('should show a start button', () => {
    expect(el('[data-test="start-btn"]')).toBeTruthy();
  });

  it('should call tracker service when start button clicked', async(() => {
    el('[data-test="start-btn"]').click();

    fixture.whenStable().then(() => {
      expect(trackerService.startTracking).toHaveBeenCalled();
    });
  }));
});

最佳答案

这是因为订阅事件没有发生过一次。我们可以通过添加检查来克服这个问题。

 ngOnDestroy() {
  if(this.trackSubscription){
    this.trackSubscription.unsubscribe();
  }
}

如果问题是在运行测试用例时出现的

 it('calls ngOnDestroy method', () => {
    component.trackSubscription= new Subscription();
    spyOn(component.trackSubscription, 'unsubscribe');
    component.ngOnDestroy();
    expect(component.trackSubscription.unsubscribe).toHaveBeenCalled();
  });

希望对你有帮助!

关于angular - 单元测试主题 : Cannot read property 'unsubscribe' of undefined,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59930709/

相关文章:

angular - 增强第三方库 Typescript

javascript - 如何获取 *ngFor 循环唯一记录

java - 如何使用 Mockito 测试 DAO?

javascript - 延迟除特定项目外的所有项目

javascript - 当使用 FromEvent RxJS 和 Angular 订阅输入标签值更改时,如何避免使用 'any'?

angular - @angular/router 将路由组件包装在 router-outlet 中以进行样式设置

json - 如何在 Angular 8 中将 json 字符串转换回对象

c++ - 计算字符指针中的字符

c# - 如何测试使用 DispatcherTimer 的类?

angular - 使用自动完成如何过滤多个属性上的对象