Moq在调用Task.WhenAll的任务之一中抛出异步异常

时间:2016-04-05 15:46:36

标签: c# task-parallel-library moq

我有许多任务要传递给Task.WhenAll调用。在我的测试中,我正在设置抛出异常的第一个任务,但我对所有任务的Tasks.WhenAll调用没有完成,并且在抛出异常时立即中断,我的假设是所有任务都将完成并返回调用Tasks.WhenAll,所以我认为Moq无法区分抛出异步和异步异常。

我希望能够允许所有任务运行,并且一旦完成所有任务,我想抓住故障任务并提取其异常并采取相应措施。我的实现是否正确,MOQ无法应对或者我必须修复我的实现,问题不在于模拟?

.grid-sizer {
   width: 16.667%;
 }
.grid-item {
    width: 33.33%;
}

我对处理器的设置

public async Task StartAsync(TextWriter log)
        {
            log = TextWriter.Synchronized(log);
            var processorTaks = _processors.Select(x => x.StartAsync(log)).ToList();
            Task.WhenAll(processorTaks).Wait();
            var innerExceptions = processorTaks.Where(x => x.Exception != null)
                .Select(x => x.Exception.InnerException)
                .ToList();
            if (innerExceptions.Any())
            {
                innerExceptions.AddRange(_processors.SelectMany(x => x.NotifierException).ToList());
                var formattedExceptions = innerExceptions
                    .Select(ex => $"{ex.Message}<\br>{ex.StackTrace}")
                    .Distinct();
                IEnumerable<Task> sendEmailTaks = _alertEmailAddresses
                    .Split('|')
                    .Select(
                        x =>
                            _smtpClient.SendMailAsync($"Notifications failed with {innerExceptions.Count()} exceptions",
                                string.Join("<\br>", formattedExceptions), x));
                var retry = _createWebRetry();
                await retry.RetryAsync(() => Task.WhenAll(sendEmailTaks), CancellationToken.None);
            }
        }

2 个答案:

答案 0 :(得分:12)

正如Bruno正确指出的那样,问题是被模拟的StartAsync同步抛出异常,而不是返回故障任务。

但是,正确的代码无法使用new Task(这将导致挂起,因为任务永远不会启动)。相反,请使用Task.FromException

FirstProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Returns(
    Task.FromException(new Exception("some exception happened."))
);

答案 1 :(得分:3)

Task.WhenAll将调用StartAsync,这将抛出。 调用线程抛出异常。在创建任务之前。

您希望StartAsync返回Task

firstProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Returns(new Task(() => { throw new Exception("err"); }));