public async Task QueryEvents_filters_events_by_stream_id(
            IMessageBus eventBus,
            Guid streamId,
            Guid otherStreamId,
            Event1 evt1,
            Event2 evt2,
            Event3 evt3,
            Event4 evt4)
        {
            // Arrange
            T   sut          = GenerateEventStore(eventBus);
            int startVersion = 1;
            var events       = new List <object>(
                from e in new object[] { evt1, evt2, evt3, evt4 }
                orderby e.GetHashCode()
                select e);

            await sut.CollectEvents(streamId, startVersion, events);

            await sut.CollectEvents(otherStreamId, startVersion, events);

            // Act
            IEnumerable <object> actual = await sut.QueryEvents(streamId, fromVersion : 1);

            // Assert
            actual.Should().BeEquivalentTo(events, c => c.WithStrictOrdering());
        }
        public async Task CollectEvents_does_not_send_messages_if_it_failed_to_save_events(
            MessageBusDouble spy, Guid streamId, int version, Event1 evt1, Event2 evt2)
        {
            // Arrange
            T sut = GenerateEventStore(eventBus: spy);
            await sut.CollectEvents(streamId, startVersion : version, new[] { evt1 });

            spy.Clear();

            // Act
            Func <Task> action = () => sut.CollectEvents(streamId, version, new[] { evt2 });

            // Assert
            await action.Should().ThrowAsync <Exception>();

            spy.Calls.Should().BeEmpty();
        }
        public async Task CollectEvents_sends_messages_correctly(
            Guid streamId,
            MessageBusDouble spy,
            int startVersion,
            Event1 evt1,
            Event2 evt2,
            Event3 evt3,
            Event4 evt4,
            TracingProperties tracingProperties)
        {
            // Arrange
            T sut = GenerateEventStore(eventBus: spy);

            object[] events = new object[] { evt1, evt2, evt3, evt4 };

            // Act
            await sut.CollectEvents(streamId, startVersion, events, tracingProperties);

            // Assert
            spy.Calls.Should().ContainSingle();

            (ImmutableArray <Message> msgs, string pk) = spy.Calls.Single();

            msgs.Should()
            .HaveCount(events.Length)
            .And.OnlyContain(x => x.TracingProperties == tracingProperties);

            VerifyData(msgs[0].Data, startVersion + 0, evt1);
            VerifyData(msgs[1].Data, startVersion + 1, evt2);
            VerifyData(msgs[2].Data, startVersion + 2, evt3);
            VerifyData(msgs[3].Data, startVersion + 3, evt4);

            void VerifyData <TPayload>(object source,
                                       long expectedVersion,
                                       TPayload expectedPayload)
            {
                source.Should().BeOfType <StreamEvent <TPayload> >();
                var data = (StreamEvent <TPayload>)source;

                data.StreamId.Should().Be(streamId);
                data.Version.Should().Be(expectedVersion);
                data.Payload.Should().BeEquivalentTo(expectedPayload);
            }

            pk.Should().Be($"{streamId}");
        }
        public async Task if_CollectEvents_failed_to_send_messages_it_sends_them_next_time(
            IMessageBus stub,
            Guid streamId,
            int startVersion,
            Event1 evt1,
            Event2 evt2,
            Event3 evt3,
            Event4 evt4)
        {
            // Arrange
            T sut = GenerateEventStore(eventBus: stub);

            Mock.Get(stub)
            .Setup(x => x.Send(It.IsAny <IEnumerable <Message> >(), It.IsAny <string>()))
            .ThrowsAsync(new InvalidOperationException());

            try
            {
                await sut.CollectEvents(streamId, startVersion, new object[] { evt1, evt2 });
            }
            catch
            {
            }

            var log = new List <(IEnumerable <Message> messages, string partitionKey)>();

            Mock.Get(stub)
            .Setup(x => x.Send(It.IsAny <IEnumerable <Message> >(), It.IsAny <string>()))
            .Callback <IEnumerable <Message>, string>((msgs, pk) => log.Add((msgs, pk)))
            .Returns(Task.CompletedTask);

            // Act
            await sut.CollectEvents(streamId, startVersion + 2, new object[] { evt3, evt4 });

            // Assert
            log.Should().HaveCount(2);

            log[0].messages.Select(x => x.Data).Should().BeEquivalentTo(new object[]
            {
                new StreamEvent <Event1>(streamId, startVersion + 0, default, evt1),