1

我正在尝试为 TPL BufferBlock 创建单元测试,并希望测试是否引发了异常。但是,测试在抛出异常之前通过。

编辑

此外,这是一个长期运行的过程,所以我不称之为完成。此过程一直运行到应用程序关闭

这是代码:

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

}

这是测试代码

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

ArgumentException 异常在 SetMessagePriority 中被正确抛出,因为“MessageType”等于 MessageType.Unknown。但是,在引发 ArgumentException 时,单元测试 EnqueueTest_UnknownMessageType 已成功通过,因为

var result = await _queue.EnqueueAsync(message);

在抛出异常之前返回“true”。如何编写测试 EnqueueTest_UnknownMessageType 以使其因抛出异常而失败?

我试过添加

[ExpectedException(typeof(ArgumentException))]

测试,但它仍然通过

4

1 回答 1

1

正如@JSteward 指出的那样,您期望看到的异常不会是您在方法Task中等待的异常的一部分。EnqueueAsync()

通读文档DataflowBlock.SendAsync()说明了以下关于返回值的内容:

如果目标在调用期间接受并使用提供的元素,则SendAsync在从调用返回时,结果Task<TResult>将完成并且其Result属性将返回true。如果目标在调用期间拒绝提供的元素,则在从调用返回时,结果Task<TResult>将完成并且其Result属性将返回false

唯一的Task意思是消息被第一个块接收或拒绝。没有提到将异常从后续块传播回原始Task.

如果您正在寻找消息类型的早期验证,您可以在您的EnqueueAsync()调用中直接进行检查,从您的数据流管道中删除该块。

否则,如果您希望这是更大数据流管道中的一个步骤,您可以注入一个BroadcastBlock<T>您可以附加“快乐路径”管道的其余部分以处理已知消息类型的块以及仅接收未知消息的块您可以在其中采取任何您想传达的操作的类型收到未知的消息类型。

于 2017-09-07T13:39:02.653 回答