public async Task SaveAndPublish_publishes_events()
        {
            // Arrange
            var    user          = new FakeUser(id: Guid.NewGuid(), username: Guid.NewGuid().ToString());
            string operationId   = Guid.NewGuid().ToString();
            var    correlationId = Guid.NewGuid();
            string contributor   = Guid.NewGuid().ToString();

            user.ChangeUsername(username: Guid.NewGuid().ToString());

            ISqlEventPublisher eventPublisher = Mock.Of <ISqlEventPublisher>();

            var sut = new SqlEventSourcedRepository <FakeUser>(
                Mock.Of <ISqlEventStore>(),
                eventPublisher,
                FakeUser.Factory);

            // Act
            await sut.SaveAndPublish(user, operationId, correlationId, contributor);

            // Assert
            Mock.Get(eventPublisher).Verify(
                x =>
                x.FlushPendingEvents(user.Id, default),
                Times.Once());
        }
        public async Task SaveAndPublish_saves_events()
        {
            // Arrange
            var    user          = new FakeUser(id: Guid.NewGuid(), username: Guid.NewGuid().ToString());
            string operationId   = Guid.NewGuid().ToString();
            var    correlationId = Guid.NewGuid();
            string contributor   = Guid.NewGuid().ToString();

            user.ChangeUsername(username: Guid.NewGuid().ToString());
            var pendingEvents = new List <IDomainEvent>(user.PendingEvents);

            ISqlEventStore eventStore = Mock.Of <ISqlEventStore>();

            var sut = new SqlEventSourcedRepository <FakeUser>(
                eventStore,
                Mock.Of <ISqlEventPublisher>(),
                FakeUser.Factory);

            // Act
            await sut.SaveAndPublish(user, operationId, correlationId, contributor);

            // Assert
            Mock.Get(eventStore).Verify(
                x =>
                x.SaveEvents <FakeUser>(pendingEvents, operationId, correlationId, contributor, default),
                Times.Once());
        }
        public async Task SaveAndPublish_saves_memento()
        {
            // Arrange
            var    user          = new FakeUser(id: Guid.NewGuid(), username: Guid.NewGuid().ToString());
            string operationId   = Guid.NewGuid().ToString();
            var    correlationId = Guid.NewGuid();
            string contributor   = Guid.NewGuid().ToString();

            IMementoStore mementoStore = Mock.Of <IMementoStore>();

            var sut = new SqlEventSourcedRepository <FakeUser>(
                Mock.Of <ISqlEventStore>(),
                Mock.Of <ISqlEventPublisher>(),
                mementoStore,
                FakeUser.Factory,
                FakeUser.Factory);

            // Act
            await sut.SaveAndPublish(user, operationId, correlationId, contributor);

            // Assert
            Mock.Get(mementoStore).Verify(
                x =>
                x.Save <FakeUser>(
                    user.Id,
                    It.Is <FakeUserMemento>(
                        p =>
                        p.Version == user.Version &&
                        p.Username == user.Username),
                    default),
                Times.Once());
        }
        public async Task SaveAndPublish_saves_events()
        {
            FakeUser user          = _fixture.Create <FakeUser>();
            string   operationId   = _fixture.Create <string>();
            var      correlationId = Guid.NewGuid();
            string   contributor   = Guid.NewGuid().ToString();

            user.ChangeUsername(_fixture.Create("username"));
            var pendingEvents = new List <IDomainEvent>(user.PendingEvents);

            await _sut.SaveAndPublish(user, operationId, correlationId, contributor);

            Mock.Get(_eventStore).Verify(
                x =>
                x.SaveEvents <FakeUser>(
                    pendingEvents,
                    operationId,
                    correlationId,
                    contributor,
                    CancellationToken.None),
                Times.Once());
        }
        public void SaveAndPublish_does_not_saves_memento_if_fails_to_save_events()
        {
            // Arrange
            var    user          = new FakeUser(id: Guid.NewGuid(), username: Guid.NewGuid().ToString());
            string operationId   = Guid.NewGuid().ToString();
            var    correlationId = Guid.NewGuid();
            string contributor   = Guid.NewGuid().ToString();

            ISqlEventStore eventStore   = Mock.Of <ISqlEventStore>();
            IMementoStore  mementoStore = Mock.Of <IMementoStore>();

            Mock.Get(eventStore)
            .Setup(
                x =>
                x.SaveEvents <FakeUser>(
                    It.IsAny <IEnumerable <IDomainEvent> >(),
                    operationId,
                    correlationId,
                    contributor,
                    default))
            .Throws <InvalidOperationException>();

            var sut = new SqlEventSourcedRepository <FakeUser>(
                eventStore,
                Mock.Of <ISqlEventPublisher>(),
                mementoStore,
                FakeUser.Factory,
                FakeUser.Factory);

            // Act
            Func <Task> action = () => sut.SaveAndPublish(user, operationId, correlationId, contributor);

            // Assert
            action.ShouldThrow <InvalidOperationException>();
            Mock.Get(mementoStore).Verify(
                x =>
                x.Save <FakeUser>(
                    user.Id,
                    It.IsAny <IMemento>(),
                    It.IsAny <CancellationToken>()),
                Times.Never());
        }