2017-09-06 2 views
0

Ich versuche Unit-Tests für einen TPL BufferBlock zu erstellen und testen, dass eine Ausnahme ausgelöst wird. Der Test wird jedoch ausgeführt, bevor die Ausnahme ausgelöst wird.TPL-Unit-Test BufferBlock Link zu TargetBlock

EDIT

Auch ist dies ein Prozess mit langer Laufzeit, so rufe ich nicht vollständig. Dieser Prozess läuft, bis die App

geschlossen ist Hier ist der Code:

public class PriorityMessageQueue 
{ 
     private BufferBlock<MyMessage> _messageBufferBlock; 
     private async Task<bool> Init() 
     { 
      var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions 
      { 
       MaxDegreeOfParallelism = Environment.ProcessorCount, 
       BoundedCapacity = 1000 
      }; 

      var prioritizeMessageBlock = new ActionBlock<MyMessage>(msg => 
      { 
       try 
       { 
        SetMessagePriority(msg); 
       } 
       catch (Exception) 
       { 
        throw; 
       } 

      }); 

      _messageBufferBlock = new BufferBlock<MyMessage>(executionDataflowBlockOptions); 
      _messageBufferBlock.LinkTo(prioritizeMessageBlock); 
     } 

     public async Task<bool> EnqueueAsync(MyMessage message) 
     { 
      if (message == null) 
      { 
       throw new ArgumentNullException(nameof(message), "The message object is NULL. Cannot enqueue a NULL object."); 
      } 

      return await _messageBufferBlock.SendAsync(message); 
     } 

     private void SetMessagePriority(MyMessage message) 
     { 
      if (message.MessageType.Equals(MessageType.Unknown)) 
      { 
       throw new ArgumentException("The SCBA Message Type is 'Unknown'. Cannot set the Message Priority on an 'Unknown' message type."); 
      } 

      switch (message.MessageType) 
      { 
       case MessageType.Admin:     
        message.MessagePriority = MessagePriority.Admin; 
        break; 
       case MessageType.AuthUser: 
        message.MessagePriority = MessagePriority.High; 
        break;     
       case MessageType.UnknownUser: 
        message.MessagePriority = MessagePriority.Normal; 
        break;     
       default: 
        message.MessagePriority = MessagePriority.Normal; 
        break; 
      } 
     } 

} 

Hier ist der Testcode

[TestClass()] 
    public class PriorityMessageQueueTests 
    { 
     private IPriorityMessageQueue _queue; 

     [TestInitialize] 
     public void Init() 
     { 
      IUnityContainer container = new UnityContainer(); 

      var logRepository = new Mock<ILogRepository>(); 

      container.RegisterInstance(logRepository.Object); 

      _queue = new PriorityMessageQueue(logRepository.Object); 
     } 

     [TestCleanup] 
     public void CleanUp() 
     { 
      _queue.Dispose(); 
     } 

     [TestMethod()] 
     [ExpectedException(typeof(ArgumentNullException))] 
     public async Task EnqueueTest_NullMessage() 
     { 
      await _queue.EnqueueAsync(null); 
     } 

     [TestMethod()] 
     public async Task EnqueueTest_UnknownMessageType() 
     { 
      var message = new MyMessage 
      { 
       Id = 1, 
       Text = "Unit Test" 
      }; 

      var result = await _queue.EnqueueAsync(message); 

      Assert.AreEqual(true, result); 
     } 

     [TestMethod()] 
     public void DequeueTest() 
     { 
      Assert.Fail(); 
     } 

     [TestMethod()] 
     public void GetNextInQueue() 
     { 
      Assert.Fail(); 
     } 
    } 

Das Argument Ausnahme richtig in SetMessagePriority geworfen wird, weil die ‚Message‘ gleich Message. Unbekannte. Doch durch die Zeit Argument der Unit-Test EnqueueTest_UnknownMessageType geworfen hat erfolgreich bestanden, weil

var result = await _queue.EnqueueAsync(message); 

kehrt ‚true‘, bevor die Ausnahme ausgelöst wird. Wie schreibe ich den Test EnqueueTest_UnknownMessageType, so dass es fehlschlägt, weil die Ausnahme ausgelöst wird?

habe ich versucht,

[ExpectedException(typeof(ArgumentException))] 

zum Test hinzufügen, aber es geht noch

+3

Dieses Beispiel sieht nicht vollständig aus. Stellen Sie eine [mcve] bereit, mit der das Problem reproduziert werden kann. – Nkosi

+0

Im Allgemeinen 'erwarten _queue.EnqueueAsync (Nachricht);' ist wahrscheinlich nicht die Ausnahme zu werfen, nach der Sie suchen. Jede Ausnahme, die in Ihrem 'ActionBlock' gefangen und geworfen wird, wird an diese Blöcke' Completion''Task' angehängt. Das ist die "Aufgabe", die Sie erwarten müssen, um die Ausnahme zu beobachten. Um mehr zu sagen, müssen Sie einen MCVE bereitstellen, wie @Nkosi darauf hingewiesen hat. – JSteward

+0

@Nkosi dieses Beispiel ist abgeschlossen. Bitte sagen Sie mir, was Ihrer Meinung nach fehlen könnte – Que

Antwort

0

Wie @JSteward wies darauf hin, die Ausnahme, die Sie erwarten, nicht Teil der Task sein zu sehen, welche Sie erwarten in der EnqueueAsync() Methode.

der docs for DataflowBlock.SendAsync() Lesen durch sagt folgendes über den Rückgabewert:

Wenn das Ziel akzeptiert und verbraucht das angebotene Element während des Anrufs SendAsync, nach der Rückkehr aus dem Aufruf der resultierende Task<TResult> abgeschlossen sein wird und seine Result Eigenschaft wird zurückgegeben true. Wenn das Ziel das angebotene Element während des Anrufs ablehnt, wird das Ergebnis Task<TResult> nach der Rückkehr aus dem Anruf vervollständigt und seine Result Eigenschaft gibt false zurück.

Die Task übermittelt nur, dass die Nachricht vom ersten Block empfangen oder abgelehnt wurde. Es gibt keine Erwähnung der Weitergabe von Ausnahmen von nachfolgenden Blöcken zurück zum ursprünglichen Task.

Wenn Sie nach einer frühzeitigen Überprüfung des Nachrichtentyps suchen, können Sie dies direkt in Ihrem EnqueueAsync()-Aufruf überprüfen und diesen Block aus Ihrer Dataflow-Pipeline entfernen.

Wenn Sie möchten, dass dies ein Schritt in einer größeren Datenfluss-Pipeline ist, können Sie einen BroadcastBlock<T> injizieren, an den Sie den Rest der "Happy Path" -Pipeline anhängen können, um die bekannten Nachrichtentypen sowie einen Block zu verarbeiten die nur unbekannte Nachrichtentypen empfängt, in denen Sie jede Aktion ausführen können, die Sie kommunizieren möchten, wurde ein unbekannter Nachrichtentyp empfangen.

+0

danke. Ich hatte bereits die Validierungslogik geändert, aber es ist schön zu wissen, dass ich mit TPL Dataflow auf dem richtigen Weg bin – Que