測試觀測量時如何使用Task.Run虛擬時間,我有以下功能我想測試與無擴展
/// 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,並允許我測試是否可以成功刪除 預期的消息。