我有一个测试代码示例:
[Fact]
public void Should_only_contain_most_recent() {
var window = TimeSpan.FromMilliseconds(200);
var results = new ReplaySubject<long>(window);
results.OnNext(1);
results.OnNext(2);
System.Threading.Thread.Sleep(50);
results.OnNext(3);
System.Threading.Thread.Sleep(50);
results.OnNext(4);
System.Threading.Thread.Sleep(200);
results.OnNext(5);
results.OnCompleted();
var items = results.ToEnumerable();
Assert.True(items.SequenceEqual(new long [] { 5 }));
}
我想使用Microsoft.Reactive.Testing包中的TestScheduler,因为我想摆脱这里的睡眠。
我已经尝试过这样的事情。
[Fact]
public void Should_only_contain_most_recent() {
var scheduler = new TestScheduler();
var window = TimeSpan.FromMilliseconds(200);
var results = new ReplaySubject<long>(window /* Never finishes when add the scheduler here.*/);
results.OnNext(1);
results.OnNext(2);
scheduler.Schedule(TimeSpan.FromMilliseconds(50), () => results.OnNext(3));
scheduler.Schedule(TimeSpan.FromMilliseconds(50), () => results.OnNext(4));
scheduler.Schedule(TimeSpan.FromMilliseconds(200), () => results.OnNext(5));
scheduler.Schedule(TimeSpan.FromMilliseconds(210), results.OnCompleted);
scheduler.Start();
var items = results.ToEnumerable();
Assert.True(items.SequenceEqual(new long[] { 5 }));
}
但我错过了一些东西。
答案 0 :(得分:1)
据推测,您正在尝试测试ReplaySubject的重放行为。问题是你需要两次启动TestScheduler。它只会运行直到所有已调度的事件都被执行 - 但是我们需要在没有任何订阅者的情况下加载ReplaySubject
以便它具有它将重放的事件 - 然后在订阅者附加后再次运行调度程序。
以下是编写此测试的惯用方法:
首先,我将source
设置为我们需要的事件。通过从ReactiveTest
派生测试类,您可以利用OnXXX辅助方法更轻松地创建源事件。
我们准备好源代码流后,我们就可以为此ReplaySubject
订阅,并在Start
上调用TestScheduler
。这将运行虚拟时间直到最后一个预定事件(T = 300ms) - 我通过转储超时来证明这一点。
现在,我们使用TestScheduler
的{{1}}方法为结果创建记录器并将其订阅到CreateObserver
。
现在我们再次启动ReplaySubject
- 这将从T = 300ms开始运行时钟,直到刷新新创建的预定事件。这些是TestScheduler
需要重播的事件 - 200ms窗口内的事件。请注意,这些将在T = 300ms + 1刻度,+ 2刻度和+3刻度处发出 - 这是因为ReplaySubject
具有1刻度分辨率。
以下是代码:
TestScheduler