[英]Moq Throw async exception in one of tasks in call to Task.WhenAll
我有许多任务要传递给 Task.WhenAll 调用。 在我的测试中,我正在设置第一个抛出异常的任务,但是我对 Tasks.WhenAll 的调用并未针对所有任务完成,并且在抛出异常时立即中断。 我的假设是当调用 Tasks.WhenAll 时所有任务都将完成并返回,所以我认为 Moq 无法区分抛出异步和非异步异常。
我希望能够允许所有任务运行,一旦所有任务都完成,我想抓住有问题的任务并提取它们的异常并采取相应的行动。 我的实现是否正确? Moq 是否无法应对,或者我是否必须修复我的实施并且问题不在于 Moq?
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);
}
}
我的处理器设置:
FirstProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Throws(new Exception("some exception happened."));
SecondProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Returns(Task.FromResult(default(object)));
正如布鲁诺正确指出的那样,问题在于模拟的StartAsync
同步抛出异常,而不是返回错误的任务。
但是,正确的代码不能使用new Task
(这将导致挂起,因为任务从未启动)。 相反,使用Task.FromException
:
FirstProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Returns(
Task.FromException(new Exception("some exception happened."))
);
Task.WhenAll
将调用StartAsync
,这将抛出。 在调用线程上抛出异常。 在创建任务之前。
您希望StartAsync
返回一个Task
:
firstProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Returns(new Task(() => { throw new Exception("err"); }));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.