I have a series of tasks that I pass to the challenge of Task.WhenAll. in my tests, I set the first task to throw an exception, but my Tasks.WhenAll call is not completed for all tasks and immediately breaks when an exception occurs, I assumed that all tasks will be completed and returned when the Tasks.WhenAll call is created, therefore I think Moq cannot distinguish between an asynchronous metacharacter and non-synchronous exceptions.
I want to be able to allow all tasks to be completed, and as soon as they are all completed, I want to capture the failed tasks and extract their exceptions and act accordingly. Is my implementation correct and the MOQ is not able to handle or do I need to fix my implementation and the problem is not in the layout?
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); } }
my setup for processors
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)));
source share