【问题标题】:Jasmine Wait for Observable SubscriptionJasmine 等待 Observable 订阅
【发布时间】:2020-12-30 16:25:20
【问题描述】:

我有以下课程:

@Injectable()
export class MyService {
  private subscriptions: { [key: string]: Subscription } = {};

  constructor(private otherService: OtherService) {
  }

  public launchTimer(order: any): void {
    this.subscriptions[order.id] = timer(500, 300000).subscribe(
      () => {
        this.otherService.notify();
      },
    );
  }
}

我想编写一个单元测试,它断言当调用 launchTimer() 时,会调用 OtherServicenotify 方法。 棘手的是,对 timer 可观察对象的订阅是直接在方法中完成的,这意味着我不能直接在单元测试中进行订阅以进行断言。
到目前为止,我想出的是以下测试失败,因为断言是在订阅之前完成的:

class OtherServiceMock {
  public notify(): void {}
}

describe('MyService', () => {
  let otherService: OtherServiceMock;
  let myService: MyService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: OtherService, useClass: OtherServiceMock },
      ],
    });
    otherService = TestBed.get(OtherService);
    myService = TestBed.get(MyService);
  });

  it('launchTimer should call notify', () => {
    spyOn(otherService, 'notify');
    myService.launchTimer();
    expect(otherService.notify).toHaveBeenCalled();
  });
});

我尝试使用 async 包装该函数,并且我还使用 fakeAsynctick 但似乎没有任何效果。 有什么想法可以在做出断言之前等待订阅吗?

【问题讨论】:

    标签: angular rxjs jasmine


    【解决方案1】:

    使用间隔和计时器测试 observables 可能会很棘手,但试试这个,如果这不起作用,我也可以用不同的方式来做。

    class OtherServiceMock {
      public notify(): void {}
    }
    
    describe('MyService', () => {
      let otherService: OtherServiceMock;
      let myService: MyService;
      beforeEach(() => {
        TestBed.configureTestingModule({
          providers: [
            { provide: OtherService, useClass: OtherServiceMock },
          ],
        });
        otherService = TestBed.get(OtherService);
        myService = TestBed.get(MyService);
      });
    
      it('launchTimer should call notify', fakeAsync(() => {
        // you're going to have to make `subscriptions` public for this to work !!
        spyOn(otherService, 'notify'); // don't need to callThrough to see if it was called or not
        myService.launchTimer({id: 1});
        tick(501);
        expect(otherService.notify).toHaveBeenCalled();
        myService.subscriptions['1'].unsubscribe(); // kill the timer subscription
      }));
    });
    

    ======================编辑========================= ==========

    您要么必须将subscriptions 公开,要么提供一种公开方式来取消订阅该对象中的订阅。

    【讨论】:

    • 不,这不起作用。我已经尝试过使用 fakeAsync 和 tick()。在这种情况下我收到此错误:1 个周期性计时器仍在队列中,这是有道理的,因为订阅已完成,但测试超时,因为我在这里使用了一个计时器
    • 我已经进行了编辑,尝试一下。顺便说一句,我关注了这篇文章:medium.com/@andrew.nguyenvo/…
    • 当您收到“计时器仍在队列中”消息时,将 tick() 时间增加一个更高的量。例如,如果您的总时间是 500 毫秒,请勾选 5000 毫秒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 2017-09-03
    相关资源
    最近更新 更多