Вот как я это делаю:
[Test]
public void ObservesTaskException()
{
bool wasUnobservedException = false;
TaskScheduler.UnobservedTaskException +=
(s, args) => wasUnobservedException = true;
CauseATaskToThrowInTheSystemUnderTest();
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.That(wasUnobservedException, Is.False);
}
Вызов CauseATaskToThrowInTheSystemUnderTest () является заполнителем для всего, что вам нужно сделать.Я рекомендую обернуть ваш код в функцию, подобную этой, потому что это помогает удостовериться, что объект Task, который генерирует исключение, недоступен при запуске GC.Если объект «Задача» достижим, финализатор не запустится, и этот тест ничего не будет проверять.
Очевидно, что важно также убедиться, что задача завершена, прежде чем произойдет сборка мусора.То, как вы это сделаете (если сможете), зависит от вашего конкретного кода.Возможно, поток вашей программы гарантирует, что это так.Если нет, и если ваш тест может получить доступ к объекту Task, вы можете сделать следующее:
var continuation = GetTheTaskFromTheSystemUnderTest();
.ContinueWith(t => {});
CauseATaskToThrowInTheSystemUnderTest();
bool isTaskCompleted = continuation.Wait(SomeSuitableTimeout);
Вы должны добавить isTaskCompleted к вашему утверждению.
Тайм-аут есть на всякий случайв будущем код не работает - вы не хотите, чтобы ваш тест зависал.Значение должно быть очень маленьким.Если вы обнаружите, что вам действительно нужно очень долго ждать своей задачи, ваш набор тестов, вероятно, будет слишком медленным для частого использования.
Доступ к задачам, которые вы создаете (включая задачи продолжения, которые вы создаете для других задач),одно из соображений, о которых следует помнить при разработке для тестирования.При этом применяются обычные компромиссы.Я стараюсь включать такие тесты, когда мой код создает задачи - это важное поведение моего кода, и его необходимо протестировать.