public async Task When_there_are_multiple_messages_and_some_are_received_and_Dispatched_bulk_Async()
        {
            await _sqlOutbox.AddAsync(_message);

            await Task.Delay(100);

            await _sqlOutbox.AddAsync(_message1);

            await Task.Delay(100);

            await _sqlOutbox.AddAsync(_message2);

            await Task.Delay(100);

            await _sqlOutbox.AddAsync(_message3);

            await Task.Delay(100);

            _messages = await _sqlOutbox.GetAsync(new[] { _message1.Id, _message2.Id });

            //should fetch 1 message
            _messages.Should().HaveCount(2);
            //should fetch expected message
            _messages.Should().Contain(m => m.Id == _message1.Id);
            _messages.Should().Contain(m => m.Id == _message2.Id);

            await _sqlOutbox.MarkDispatchedAsync(_messages.Select(m => m.Id), DateTime.UtcNow);

            var undispatchedMessages = await _sqlOutbox.OutstandingMessagesAsync(0);

            undispatchedMessages.Count().Should().Be(2);
        }
        public async Task When_The_Message_Is_Already_In_The_Outbox_Async()
        {
            await _sqlOutbox.AddAsync(_messageEarliest);

            _exception = await Catch.ExceptionAsync(() => _sqlOutbox.AddAsync(_messageEarliest));

            //should ignore the duplcate key and still succeed
            _exception.Should().BeNull();
        }
        private async Task SetUpMessagesAsync()
        {
            _messageEarliest = new Message(new MessageHeader(Guid.NewGuid(), "Test", MessageType.MT_COMMAND, DateTime.UtcNow.AddHours(-3)), new MessageBody("Body"));
            await _sqlOutbox.AddAsync(_messageEarliest);

            _message2 = new Message(new MessageHeader(Guid.NewGuid(), "Test2", MessageType.MT_COMMAND, DateTime.UtcNow.AddHours(-2)), new MessageBody("Body2"));
            await _sqlOutbox.AddAsync(_message2);

            _messageLatest = new Message(new MessageHeader(Guid.NewGuid(), "Test3", MessageType.MT_COMMAND, DateTime.UtcNow.AddHours(-1)), new MessageBody("Body3"));
            await _sqlOutbox.AddAsync(_messageLatest);
        }
        public async Task When_Writing_A_Message_To_The_Outbox_Async()
        {
            await _sqlOutbox.AddAsync(_messageEarliest);

            _storedMessage = await _sqlOutbox.GetAsync(_messageEarliest.Id);

            //should read the message from the sql outbox
            _storedMessage.Body.Value.Should().Be(_messageEarliest.Body.Value);
            //should read the header from the sql outbox
            _storedMessage.Header.Topic.Should().Be(_messageEarliest.Header.Topic);
            _storedMessage.Header.MessageType.Should().Be(_messageEarliest.Header.MessageType);
            _storedMessage.Header.TimeStamp.Should().Be(_messageEarliest.Header.TimeStamp);
            _storedMessage.Header.HandledCount.Should().Be(0);        // -- should be zero when read from outbox
            _storedMessage.Header.DelayedMilliseconds.Should().Be(0); // -- should be zero when read from outbox
            _storedMessage.Header.CorrelationId.Should().Be(_messageEarliest.Header.CorrelationId);
            _storedMessage.Header.ReplyTo.Should().Be(_messageEarliest.Header.ReplyTo);
            _storedMessage.Header.ContentType.Should().Be(_messageEarliest.Header.ContentType);


            //Bag serialization
            //should read the message header first bag item from the sql outbox
            _storedMessage.Header.Bag.ContainsKey(_key1).Should().BeTrue();
            _storedMessage.Header.Bag[_key1].Should().Be(_value1);
            //should read the message header second bag item from the sql outbox
            _storedMessage.Header.Bag.ContainsKey(_key2).Should().BeTrue();
            _storedMessage.Header.Bag[_key2].Should().Be(_value2);
        }
        public async Task When_There_Are_Multiple_Messages_In_The_Outbox_And_A_Range_Is_Fetched_Async()
        {
            await _sqlOutbox.AddAsync(_messageEarliest);

            await Task.Delay(100);

            await _sqlOutbox.AddAsync(_message1);

            await Task.Delay(100);

            await _sqlOutbox.AddAsync(_message2);

            _messages = await _sqlOutbox.GetAsync(1, 3);

            //_should_fetch_1_message
            _messages.Should().HaveCount(1);
            //_should_fetch_expected_message
            _messages.First().Header.Topic.Should().Be(_TopicLastMessage);
            //_should_not_fetch_null_messages
            _messages.Should().NotBeNull();
        }
        public async Task When_Writing_A_Message_To_The_Outbox_Async()
        {
            await _sqlOutbox.AddAsync(_messageEarliest);

            _storedMessage = await _sqlOutbox.GetAsync(_messageEarliest.Id);

            //_should_read_the_message_from_the__sql_outbox =
            _storedMessage.Body.Value.Should().Be(_messageEarliest.Body.Value);
            //_should_read_the_message_header_first_bag_item_from_the__sql_outbox
            _storedMessage.Header.Bag.ContainsKey(_key1).Should().BeTrue();
            _storedMessage.Header.Bag[_key1].Should().Be(_value1);
            //_should_read_the_message_header_second_bag_item_from_the__sql_outbox
            _storedMessage.Header.Bag.ContainsKey(_key2).Should().BeTrue();
            _storedMessage.Header.Bag[_key2].Should().Be(_value2);
            //_should_read_the_message_header_timestamp_from_the__sql_outbox
            _storedMessage.Header.TimeStamp.Should().Be(_messageEarliest.Header.TimeStamp);
            //_should_read_the_message_header_topic_from_the__sql_outbox
            _storedMessage.Header.Topic.Should().Be(_messageEarliest.Header.Topic);
            //_should_read_the_message_header_type_from_the__sql_outbox
            _storedMessage.Header.MessageType.Should().Be(_messageEarliest.Header.MessageType);
        }