テストしたい次の機能があります
/// Items are processed asynchronously via fn as they arrive. However
/// if an item arrives before the last asynchronous operation has
/// completed then the cancellation token passed to fn will be
/// triggered enabling the task to be canceled in a best effort
/// way.
public static IObservable<U> SelectWithCancellation<T, U>
( this IObservable<T> This
, Func<CancellationToken, T, Task<U>> fn
)
{
return This
.Select(v=>Observable.FromAsync(token=>fn(token, v)))
.Switch();
}
私はそれをテストしたいと思います。私が思いついた最高のものは以下のとおりです。最初に、キャンセル可能な長時間実行タスクを作成します
public Task<string> JobTask
( CancellationToken token
, string input
)
{
return Task.Factory.StartNew(() =>
{
if ( input == "C" || input == "E" )
{
while ( !token.IsCancellationRequested ) ;
}
return input;
}
);
}
そして、それが実際に機能することをテストします
public class SelectWithCancelationSpec : ReactiveTest
{
TestScheduler _Scheduler = new TestScheduler();
[Fact]
public void ShouldWork()
{
var o = _Scheduler.CreateHotObservable
( OnNext(100, "A")
, OnNext(200, "B")
, OnNext(300, "C")
, OnNext(400, "D")
, OnNext(500, "E")
, OnNext(500, "F")
);
List<string> actual = new List<string>();
o
.SelectWithCancellation(JobTask)
.Subscribe(v => actual.Add(v));
var delay = 100;
_Scheduler.AdvanceTo(150);
Thread.Sleep(delay);
_Scheduler.AdvanceTo(250);
Thread.Sleep(delay);
_Scheduler.AdvanceTo(350);
Thread.Sleep(delay);
_Scheduler.AdvanceTo(450);
Thread.Sleep(delay);
_Scheduler.AdvanceTo(550);
Thread.Sleep(delay);
_Scheduler.AdvanceTo(650);
var expected = new[] { "A", "B", "D", "F" };
actual
.ShouldBeEquivalentTo(expected);
}
}
real time
問題は、私がテストに導入しなければならなかったことです. これは、シミュレートした JobTask がスレッド プールの実際のスレッドで実行されており、テスト スケジューラの仮想時間を考慮していないためです。呼び出しの間に遅延を入れないAdvanceTo
と、JobTask の処理に時間がかかりすぎるため、テストで予想したよりも多くのメッセージがドロップされます。
質問は。仮想時間を尊重し、意図したメッセージを正常にドロップできるかどうかをテストできる JobTask を作成するにはどうすればよいですか。