RxJS测试Observable序列而不传递调度程序

时间:2016-02-04 09:14:08

标签: javascript rxjs

我在尝试测试与以下函数类似的代码时遇到问题。

基本上问题归结为:是否可以更改debounce运算符的调度程序而不将单独的Scheduler传递给函数调用?

以下示例应该更具体地解释用例。我试图测试一段类似于以下的代码。我想测试函数中的链(使用TestScheduler),而不必将调度程序传递给debounce()运算符。

// Production code
function asyncFunctionToTest(subject) {
  subject
    .tap((v) => console.log(`Tapping: ${v}`))
    .debounce(1000)
    .subscribe((v) => {
      // Here it would call ReactComponent.setState()
      console.log(`onNext: ${v}`)
    });
}

测试文件将包含以下代码以调用该函数并确保主题发出值。

// Testfile
const testScheduler = new Rx.TestScheduler();
const subject = new Rx.Subject();

asyncFunctionToTest(subject);

testScheduler.schedule(200, () => subject.onNext('First'));
testScheduler.schedule(400, () => subject.onNext('Second'))
testScheduler.advanceTo(1000);

上面的测试代码仍然需要一秒实际的去抖动。我找到的唯一解决方案是将TestScheduler传递给函数并将其传递给debounce(1000, testScheduler)方法。这将使debounce运算符使用测试调度程序。

我最初的想法是使用observeOnsubscribeOn来更改整个操作链中使用的 defaultScheduler ,方法是更改​​

asyncFunctionToTest(subject);

类似于asyncFunctionToTest(subject.observeOn(testScheduler));asyncFunctionToTest(subject.subscribeOn(testScheduler));

这并没有像我预期的那样给出结果,但我认为我可能不完全理解observeOnsubscribeOn运算符的工作方式。 (我现在估计,当使用这些运算符时,它会更改调度程序,运行整个操作链,但运算符仍然选择自己的调度程序,除非特别传递?)

以下JSBin包含我在调度程序中传递的可运行示例。 http://jsbin.com/kiciwiyowe/1/edit?js,console

1 个答案:

答案 0 :(得分:1)

不,不是真的,除非您实际修补了RxJS库。我知道这最近是作为issue提出的,可能有支持说,能够在将来某个时候更改DefaultScheduler,但此时它无法可靠地完成。

有什么理由不能包含调度程序吗?所有接受调度程序的运算符都已经选择并且具有合理的默认值,因此只要您的生产代码可以忽略该参数,它就不会给您带来任何损失。

除了更简单地添加observeOnsubscribeOn并不能解决这个问题之外,这两个运算符实际上只会影响之后传播事件的方式已被该运营商收到。

例如,您可以通过执行以下操作来实现observeOn

Rx.Observable.prototype.observeOn = (scheduler) => {
  var source = this;
  return Rx.Observable.create((observer) => {
    source.subscribe(x => 
       {
         //Reschedule this for a later propagation
         scheduler.schedule(x, 
             (s, state) => observer.onNext(state)); 
       },
       //Errors get forwarded immediately
       e => observer.onError(e),
       //Delay completion 
       () => scheduler.schedule(null, () => observer.onCompleted()))
  });

};

上述所有操作都是重新安排传入事件,如果操作员在下游或上游有其他延迟,则此操作符对它们没有影响。 subscribeOn具有类似的行为,除了它重新安排订阅而不是事件。