public void OnAsyncVoidEventHandlersAndExceptionHandling()
        {
            var _locker = new object();
            // this kind of declaration does not happend in real life but remind it is just a contextual mock.
            IMessageAPI    msgApi = new MessageQueue();
            IMessageSender sender = msgApi as IMessageSender;
            // our message worker
            var msgWorker = new MessageConsummer();

            // register our action to be done on each recieved message
            // this kind of pattern can be found with RabbitMQ client library for example,
            // it is a real life pattern and we should pay attention to not fall into a trap.
            msgApi.Received += msgWorker.Message_Received_But_Exception_On_processing;
            msgApi.OnError  += msgWorker.ErrorHandler;
            // -----------------------------------------
            var msg = new Message("Test context", $"0");

            void MessageProducer()
            {
                sender.Push(msg);
                lock (_locker)
                {
                    Monitor.Pulse(_locker);
                }
            }

            (new Task(MessageProducer)).Start();
            lock (_locker)
            {
                Monitor.Wait(_locker);
            }
            var count = 0;

            msgWorker.Foreach(MessageConsummerCase.Error, (errorMsg) => { Assert.Equal($"Error on: {msg.Body} with error type: {typeof(TimeoutException).Name}", errorMsg); count++; });
            Assert.Equal(1, count);
            msgWorker.Foreach((ex) => Assert.Equal("Can not process message in time.", ex.Message));
        }
        public void OnAsyncVoidEventHandlers()
        {
            var _locker = new object();
            // this kind of declaration does not happend in real life but remind it is just a contextual mock.
            IMessageAPI    msgApi = new MessageQueue();
            IMessageSender sender = msgApi as IMessageSender;
            // our message worker
            var msgWorker = new MessageConsummer();

            // register our action to be done on each recieved message
            msgApi.Received += msgWorker.Message_Received;
            // -----------------------------------------
            void MessageProducer()
            {
                for (int i = 0; i < 10; i++)
                {
                    var msg = new Message("Test context", $"{i}");
                    sender.Push(msg);
                }
                lock (_locker)
                {
                    Monitor.Pulse(_locker);
                }
            }

            (new Task(MessageProducer)).Start();
            lock (_locker)
            {
                Monitor.Wait(_locker);
            }
            var count = 0;

            msgWorker.Foreach(MessageConsummerCase.Received, (msg) => Assert.Equal($"Received: {count++}", msg));
            count = 0;
            msgWorker.Foreach(MessageConsummerCase.Processed, (msg) => Assert.Equal($"Processed: {count++}", msg));
        }