を、ここでのタスクを作成する方法です。あなたが遅延をテストするために仮想時間を使うことができるように、反応性ExtensionsのISchedulerを使用していますディレイ:
using System;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
public static class TaskEx
{
public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken = default(CancellationToken))
{
#if TEST
return Observable.Timer(TimeSpan.FromMilliseconds(millisecondsDelay), AppContext.DefaultScheduler).ToTask(cancellationToken);
#else
return Task.Delay(millisecondsDelay, cancellationToken);
#endif
}
}
これは、ユニットテストされていない場合、完全にRxのを避けるために、コンパイルシンボルを使用しています。
AppContextはスケジューラへの参照を持つコンテキストオブジェクトです。あなたのテストでは、AppContext.DefaultScheduler = testScheduler
を設定することができ、遅延は仮想タイムスケジューラによって引き起こされます。
ただし、注意が必要です。 TestSchedulerは同期式なので、タスクがスケジュールされる前にスケジューラが前進するので、タスクを開始してTaskEx.Delayを使用することはできません。
var scheduler = new TestScheduler();
AppContext.DefaultScheduler = scheduler;
Task.Run(async() => {
await TaskEx.Delay(100);
Console.Write("Done");
});
/// this won't work, Task.Delay didn't run yet.
scheduler.AdvanceBy(1);
代わりに、あなたは常にObservable.Start(task, scheduler)
を使用してタスクを開始する必要があり、そのタスクが順番に実行されます。
var scheduler = new TestScheduler();
AppContext.DefaultScheduler = scheduler;
Observable.Start(async() => {
await TaskEx.Delay(100);
Console.Write("Done");
}, scheduler);
/// this runs the code to schedule de delay
scheduler.AdvanceBy(1);
/// this actually runs until the delay is complete
scheduler.AdvanceBy(TimeSpan.FromMilliseconds(100).Ticks);
これは確かに複雑ですので、私はどこでも私は、タスクを使用して、それを使用することはありません。ディレイ。しかし、遅延がアプリケーションの動作を変更し、あなたがそれをテストする必要があるコードのいくつかの特定の部分があるので、これらの特別な場合に便利です。
あなたは、後者のオプションがどのように実行できるかについていくつか詳しく説明していますか? –
私はまだブログ記事を書いていませんが、[コードはこちらです](https://github.com/StephenCleary/Presentations/tree/ba85a29179091e86743ba0f45c01a1d93fb43f4b/Async%20Unit%20Testing/Demos/Timing) –
どのようにしましたか?偽を作成できるように、mscorlib.dllへの参照を追加しますか? – Choco