2016-04-05 10 views
4

Task.WhenAll呼び出しに渡すタスクがいくつかあります。私のテストでは例外をスローする最初のタスクを設定していますが、Tasks.WhenAllへの呼び出しはすべてのタスクで完了せず、例外がスローされたときにすぐに破損します。私の前提はすべてのタスクが完了し、 Tasks.WhenAllへの呼び出しが行われるので、Moqは非同期例外と非同期例外を区別することができません。Moq Task.WhenAllの呼び出しでタスクの1つで非同期例外をスローする

私はすべてのタスクを実行できるようにしたいと思うし、それらのすべてが完了したら、フォールトされたタスクをつかみ、その例外を抽出してそれに応じて行動したいと思います。私の実装は正しいですか?MOQは対処できませんか、実装を修正する必要がありますか?問題はモックではありませんか?プロセッサ

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))); 

答えて

8

ブルーノが正しく指摘したように、問題は嘲笑StartAsyncは、障害の発生したタスクを返さない、同期例外をスローしていることです。

ただし、正しいコードではnew Taskを使用できません(これは、タスクが開始されていないためハングすることになります)。

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

注:代わりに、Task.FromExceptionを使用Task.FromExceptionは、.NET Frameworkの4.6で公開されているし、以前のバージョンで – ChrisM

+1

@ChrisMをこのように使用することはできません:真。古いバージョンの場合は、 'TaskCompletionSource'と' SetException'を使う必要があります。 –

3

Task.WhenAllため

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); 
      } 
     } 

私のセットアップがスローされますよう、StartAsyncを呼び出します。 呼び出し側のスレッドで例外がスローされます。タスクを作成する前に

あなたはStartAsyncTaskを返すようにしたい:

firstProcessor.Setup(x => x.StartAsync(It.IsAny<TextWriter>())).Returns(new Task(() => { throw new Exception("err"); })); 
関連する問題