Во время модульного тестирования я получил странные неудачные тестовые случаи. В конце концов все свелось к повторению; Я мог бы даже запустить один и тот же тест несколько раз и получить положительный результат только при первом запуске.
Вот код моего класса AutoCancelTask (извините за довольно длинный код... Я пытался создайте минимальный функциональный пример, который вы сможете скопировать и вставить...):
Код: Выделить всё
using System;
using System.Threading.Tasks;
using System.Threading;
namespace Tests
{
///
/// A Task that is cancelled and waited for, when disposed.
///
public class AutoCancelTask : Task
{
private readonly CancellationTokenSource _cts;
private AutoCancelTask(Action action, CancellationTokenSource cts, TaskCreationOptions options)
: base(() => action(cts.Token), cts.Token, options)
{
_cts = cts;
}
///
/// Wrap a cancellable Action in a Task that is automatically cancelled and waited for when disposed.
///
/// The Action to wrap.
/// The TaskCreationOptions to use.
/// The started task.
public static Task Run(Action action, TaskCreationOptions options = TaskCreationOptions.None)
{
Task t = new AutoCancelTask(action, new CancellationTokenSource(), options);
t.Start();
return t;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
try
{
_cts.Cancel();
}
catch (ObjectDisposedException)
{
// nothing to do in this case
}
try
{
Wait();
}
catch (ObjectDisposedException) { }
catch (AggregateException ex)
{
if (1 < ex.InnerExceptions.Count || false == (ex.InnerExceptions[0] is TaskCanceledException))
{
// rethrow if the aggregate does not contain a single TaskCancelledException
throw ex;
}
}
_cts.Dispose();
}
base.Dispose(disposing);
}
}
}
Код: Выделить всё
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
namespace Tests
{
public class TestDataWrapper
{
internal bool? IsCancelled { get; private set; } = null;
internal void Action(CancellationToken cancel)
{
IsCancelled = Task.Delay(100, cancel).ContinueWith(t => t.IsCanceled).Result;
}
}
[TestClass()]
public class Tests
{
public static IEnumerable Datas { get; } =
Enumerable.Range(0, 5).Select(_ => new object[] { new TestDataWrapper() });
[DataTestMethod]
[DynamicData(nameof(Datas))]
public void AutoCancelTask_Cancels(TestDataWrapper data)
{
using (AutoCancelTask.Run(data.Action)) { }
Assert.AreEqual(true, data.IsCancelled);
}
}
}
Интересно, что время выполнения также варьируется:
Выполнение 1: ~30 мс
Выполнение 2: ~300 мсВыполнение 4-5:
Подробнее здесь: https://stackoverflow.com/questions/790 ... -instances
Мобильная версия