我有一个测试代码示例:
[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 }));
}
但是我缺少了一些东西。
最佳答案
大概您正在尝试测试ReplaySubject的重播行为。问题是您需要两次启动TestScheduler。它仅在执行所有计划的事件之前一直运行-但是我们需要在没有任何订阅服务器的情况下加载ReplaySubject
,以便它具有将要重播的事件-然后在订阅服务器连接后再次运行调度程序。
这是编写此测试的惯用方式:
首先,我为source
设置了我们需要的事件。通过从ReactiveTest
派生测试类,您可以利用OnXXX helper方法更轻松地创建源事件。
准备好源流之后,我们可以预订ReplaySubject
并在Start
上调用TestScheduler
。这将使虚拟时间一直运行到最后安排的事件(T = 300ms)-我通过转储超时来演示这一点。
现在,我们使用TestScheduler
的CreateObserver
方法为结果创建记录器,并将其预订为ReplaySubject
。
现在,我们再次启动TestScheduler
-从T = 300ms开始运行时钟,直到刷新新创建的计划事件。这些是ReplaySubject
需要重播的事件-200ms窗口内的事件。请注意,这些将在T = 300ms + 1个滴答声,+ 2个滴答声和+ 3个滴答声时发出-这是因为TestScheduler
具有1个滴答声分辨率。
这是代码:
public class MyTests : ReactiveTest
{
[Fact]
public void Should_only_contain_most_recent()
{
var scheduler = new TestScheduler();
var source = scheduler.CreateHotObservable(
OnNext(0, 1),
OnNext(0, 2),
OnNext(TimeSpan.FromMilliseconds(50).Ticks, 3),
OnNext(TimeSpan.FromMilliseconds(100).Ticks, 4),
OnNext(TimeSpan.FromMilliseconds(300).Ticks, 5),
OnCompleted(TimeSpan.FromMilliseconds(300).Ticks, witness: 0));
var replaySubject = new ReplaySubject<int>(
TimeSpan.FromMilliseconds(200), scheduler);
source.Subscribe(replaySubject);
scheduler.Start();
/* the test scheduler is now at 300 milliseconds
* and the ReplaySubject is loaded */
Console.WriteLine(scheduler.Now.Ticks);
var results = scheduler.CreateObserver<int>();
replaySubject.Subscribe(results);
/* run the scheduler on to flush the events from the ReplaySubject */
scheduler.Start();
results.Messages.AssertEqual(
OnNext(TimeSpan.FromMilliseconds(300).Ticks + 1, 4),
OnNext(TimeSpan.FromMilliseconds(300).Ticks + 2, 5),
OnCompleted(TimeSpan.FromMilliseconds(300).Ticks + 3, witness: 0));
}
}
关于c# - 如何在窗口ReplaySubject时间内使用TestScheduler,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25102256/