на основе АЛЕКСЕЙ anwser создать оболочку для Task.Delay, вот как создать задачу.Задержка, которая использует 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);
Это, конечно, сложнее, так что я бы не использовать его везде я использую задачу. Задержка. Но есть некоторые конкретные фрагменты кода, в которых задержка изменяет поведение приложения, и вам нужно проверить это, поэтому оно полезно для этих особых случаев.
Coul Вы предоставляете более подробную информацию о том, как можно использовать последний вариант? –
Я еще не написал запись в блоге, но [вот какой код] (https://github.com/StephenCleary/Presentations/tree/ba85a29179091e86743ba0f45c01a1d93fb43f4b/Async%20Unit%20Testing/Demos/Timing) –
как вы добавьте ссылку на mscorlib.dll, чтобы создать фальшивку? – Choco