public async Task SaveEvents_inserts_UniqueIndexedProperty_with_value_of_latest_indexed_event()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();
            var events          = new DomainEvent[] { created, usernameChanged };

            events.Raise(userId);

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            await sut.SaveEvents <FakeUser>(events);

            // Assert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                UniqueIndexedProperty actual = await db
                                               .UniqueIndexedProperties
                                               .Where(
                    p =>
                    p.AggregateId == userId &&
                    p.PropertyName == nameof(FakeUserCreated.Username))
                                               .SingleOrDefaultAsync();

                actual.PropertyValue.Should().Be(usernameChanged.Username);
                actual.Version.Should().Be(usernameChanged.Version);
            }
        }
Ejemplo n.º 2
0
        public async Task SaveEvents_updates_Aggregate_correctly_for_existing_aggregate_id(
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            using (var db = new DataContext())
            {
                var aggregate = new Aggregate
                {
                    AggregateId   = userId,
                    AggregateType = typeof(FakeUser).FullName,
                    Version       = 1
                };
                db.Aggregates.Add(aggregate);
                await db.SaveChangesAsync();
            }
            var events = new DomainEvent[] { usernameChanged };

            RaiseEvents(userId, 1, usernameChanged);

            // Act
            await sut.SaveEvents <FakeUser>(events);

            // Assert
            using (var db = new DataContext())
            {
                Aggregate actual = await db
                                   .Aggregates
                                   .Where(a => a.AggregateId == userId)
                                   .SingleOrDefaultAsync();

                actual.Version.Should().Be(usernameChanged.Version);
            }
        }
        public async Task PublishPendingEvents_deletes_pending_events(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            var sourceId = Guid.NewGuid();

            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(sourceId, events);

            using (var db = new DataContext())
            {
                foreach (DomainEvent e in events)
                {
                    var envelope = new Envelope(e);
                    db.PendingEvents.Add(PendingEvent.FromEnvelope(envelope, serializer));
                }
                await db.SaveChangesAsync();
            }

            // Act
            await sut.PublishPendingEvents(sourceId, CancellationToken.None);

            // Assert
            using (var db = new DataContext())
            {
                bool actual = await db
                              .PendingEvents
                              .Where(e => e.AggregateId == sourceId)
                              .AnyAsync();

                actual.Should().BeFalse();
            }
        }
        public void SaveEvents_fails_if_events_not_have_same_source_id()
        {
            // Arrange
            var userId  = Guid.NewGuid();
            var created = new FakeUserCreated
            {
                SourceId = userId,
                Version  = 1,
                RaisedAt = DateTime.UtcNow,
            };

            var usernameChanged = new FakeUsernameChanged
            {
                SourceId = Guid.NewGuid(),
                Version  = 2,
                RaisedAt = DateTime.UtcNow,
            };

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            Func <Task> action = () => sut.SaveEvents <FakeUser>(new DomainEvent[] { created, usernameChanged });

            // Assert
            action.ShouldThrow <ArgumentException>().Where(x => x.ParamName == "events");
        }
Ejemplo n.º 5
0
        public async Task SaveEvents_fails_if_version_of_first_event_not_follows_aggregate(
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            using (var db = new DataContext())
            {
                var aggregate = new Aggregate
                {
                    AggregateId   = userId,
                    AggregateType = typeof(FakeUser).FullName,
                    Version       = 1
                };
                db.Aggregates.Add(aggregate);
                await db.SaveChangesAsync();
            }
            var events = new DomainEvent[] { usernameChanged };

            RaiseEvents(userId, 2, usernameChanged);

            // Act
            Func <Task> action = () => sut.SaveEvents <FakeUser>(events);

            // Assert
            action.ShouldThrow <ArgumentException>()
            .Where(x => x.ParamName == "events");
        }
        public async Task SaveEvents_fails_if_version_of_first_event_not_follows_aggregate()
        {
            // Arrange
            var userId = Guid.NewGuid();

            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                var aggregate = new Aggregate
                {
                    AggregateId   = userId,
                    AggregateType = typeof(FakeUser).FullName,
                    Version       = 1,
                };
                db.Aggregates.Add(aggregate);
                await db.SaveChangesAsync();
            }

            var usernameChanged = new FakeUsernameChanged();

            usernameChanged.Raise(userId, 2);

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            Func <Task> action = () => sut.SaveEvents <FakeUser>(new[] { usernameChanged });

            // Assert
            action.ShouldThrow <ArgumentException>().Where(x => x.ParamName == "events");
        }
Ejemplo n.º 7
0
        public async Task SaveEvents_sets_message_properties_correctly(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged,
            Guid correlationId)
        {
            // Arrange
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(userId, events);

            // Act
            await sut.SaveEvents <FakeUser>(events, correlationId);

            // Asseert
            using (var db = new DataContext())
            {
                IEnumerable <object> expected = db
                                                .PendingEvents
                                                .Where(e => e.AggregateId == userId)
                                                .OrderBy(e => e.Version)
                                                .AsEnumerable()
                                                .Select(e => new { e.MessageId, e.CorrelationId })
                                                .ToList();

                IEnumerable <object> actual = db
                                              .PersistentEvents
                                              .Where(e => e.AggregateId == userId)
                                              .OrderBy(e => e.Version)
                                              .AsEnumerable()
                                              .Select(e => new { e.MessageId, e.CorrelationId })
                                              .ToList();

                actual.ShouldAllBeEquivalentTo(expected);
            }
        }
Ejemplo n.º 8
0
        public async Task SaveEvents_removes_existing_UniqueIndexedProperty_if_property_value_is_null(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            RaiseEvents(userId, created);
            await sut.SaveEvents <FakeUser>(new[] { created });

            usernameChanged.Username = null;
            RaiseEvents(userId, 1, usernameChanged);

            // Act
            await sut.SaveEvents <FakeUser>(new[] { usernameChanged });

            // Assert
            using (var db = new DataContext())
            {
                UniqueIndexedProperty actual = await db
                                               .UniqueIndexedProperties
                                               .Where(
                    p =>
                    p.AggregateType == typeof(FakeUser).FullName &&
                    p.PropertyName == nameof(FakeUserCreated.Username) &&
                    p.PropertyValue == created.Username)
                                               .SingleOrDefaultAsync();

                actual.Should().BeNull();
            }
        }
Ejemplo n.º 9
0
        public async Task SaveEvents_updates_existing_UniqueIndexedProperty_correctly(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            RaiseEvents(userId, created);
            await sut.SaveEvents <FakeUser>(new[] { created });

            RaiseEvents(userId, 1, usernameChanged);

            // Act
            await sut.SaveEvents <FakeUser>(new[] { usernameChanged });

            // Assert
            using (var db = new DataContext())
            {
                UniqueIndexedProperty actual = await db
                                               .UniqueIndexedProperties
                                               .Where(
                    p =>
                    p.AggregateId == userId &&
                    p.PropertyName == nameof(FakeUserCreated.Username))
                                               .SingleOrDefaultAsync();

                actual.Should().NotBeNull();
                actual.PropertyValue.Should().Be(usernameChanged.Username);
                actual.Version.Should().Be(usernameChanged.Version);
            }
        }
        public async Task SaveEvents_throws_DuplicateCorrelationException_if_correlation_duplicate()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();

            new DomainEvent[] { created, usernameChanged }.Raise(userId);

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            var correlationId = Guid.NewGuid();

            await sut.SaveEvents <FakeUser>(new[] { created }, correlationId : correlationId);

            // Act
            Func <Task> action = () =>
                                 sut.SaveEvents <FakeUser>(new[] { usernameChanged }, correlationId: correlationId);

            // Assert
            action.ShouldThrow <DuplicateCorrelationException>().Where(
                x =>
                x.SourceType == typeof(FakeUser) &&
                x.SourceId == userId &&
                x.CorrelationId == correlationId &&
                x.InnerException is DbUpdateException);
        }
        public async Task PublishPendingEvents_commits_once(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            var sourceId = Guid.NewGuid();

            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(sourceId, events);

            Mock.Get(mockDbContext.PendingEvents)
            .SetupData(events
                       .Select(e => new Envelope(e))
                       .Select(e => PendingEvent.FromEnvelope(e, serializer))
                       .ToList());

            var sut = new SqlEventPublisher(
                () => mockDbContext, serializer, messageBus);

            // Act
            await sut.PublishPendingEvents(sourceId, CancellationToken.None);

            // Assert
            Mock.Get(mockDbContext).Verify(
                x => x.SaveChangesAsync(CancellationToken.None),
                Times.Once());
        }
        public async Task SaveEvents_saves_pending_events_correctly()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();
            var events          = new DomainEvent[] { created, usernameChanged };

            events.Raise(userId);

            var serializer = new JsonMessageSerializer();

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                serializer);

            string operationId   = Guid.NewGuid().ToString();
            var    correlationId = Guid.NewGuid();
            string contributor   = Guid.NewGuid().ToString();

            // Act
            await sut.SaveEvents <FakeUser>(events, operationId, correlationId, contributor);

            // Asseert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                var pendingEvents = db
                                    .PendingEvents
                                    .Where(e => e.AggregateId == userId)
                                    .OrderBy(e => e.Version)
                                    .ToList();

                foreach (var t in pendingEvents.Zip(events, (pending, source) =>
                                                    new { Pending = pending, Source = source }))
                {
                    var actual = new
                    {
                        t.Pending.Version,
                        t.Pending.CorrelationId,
                        t.Pending.Contributor,
                        Message = serializer.Deserialize(t.Pending.EventJson),
                    };
                    actual.ShouldBeEquivalentTo(new
                    {
                        t.Source.Version,
                        OperationId   = operationId,
                        CorrelationId = correlationId,
                        Contributor   = contributor,
                        Message       = t.Source,
                    },
                                                opts => opts.RespectingRuntimeTypes());
                }
            }
        }
Ejemplo n.º 13
0
        public async Task FlushPendingEvents_sends_events_correctly()
        {
            // Arrange
            FakeUserCreated     created         = _fixture.Create <FakeUserCreated>();
            FakeUsernameChanged usernameChanged = _fixture.Create <FakeUsernameChanged>();
            var    sourceId      = Guid.NewGuid();
            string operationId   = _fixture.Create <string>();
            var    correlationId = Guid.NewGuid();
            string contributor   = _fixture.Create <string>();

            var domainEvents = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(sourceId, domainEvents);

            var envelopes = new List <Envelope>();

            using (var db = new DataContext())
            {
                foreach (DomainEvent domainEvent in domainEvents)
                {
                    var envelope = new Envelope(Guid.NewGuid(), domainEvent, operationId, correlationId, contributor);
                    envelopes.Add(envelope);
                    db.PendingEvents.Add(PendingEvent.FromEnvelope(envelope, _serializer));
                }

                await db.SaveChangesAsync();
            }

            List <Envelope> batch = null;

            Mock.Get(_messageBus)
            .Setup(
                x =>
                x.Send(
                    It.IsAny <IEnumerable <Envelope> >(),
                    It.IsAny <CancellationToken>()))
            .Callback <IEnumerable <Envelope>, CancellationToken>((b, t) => batch = b.ToList())
            .Returns(Task.FromResult(true));

            // Act
            await _sut.FlushPendingEvents(sourceId, CancellationToken.None);

            // Assert
            Mock.Get(_messageBus).Verify(
                x =>
                x.Send(
                    It.IsAny <IEnumerable <Envelope> >(),
                    CancellationToken.None),
                Times.Once());
            batch.ShouldAllBeEquivalentTo(envelopes, opts => opts.RespectingRuntimeTypes());
        }
        public async Task SaveEvents_saves_events_correctly()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();
            var events          = new DomainEvent[] { created, usernameChanged };

            events.Raise(userId);

            var serializer = new JsonMessageSerializer();

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                serializer);

            // Act
            await sut.SaveEvents <FakeUser>(events);

            // Asseert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                IEnumerable <object> actual = db
                                              .PersistentEvents
                                              .Where(e => e.AggregateId == userId)
                                              .OrderBy(e => e.Version)
                                              .AsEnumerable()
                                              .Select(e => new
                {
                    e.AggregateType,
                    e.Version,
                    e.EventType,
                    Payload = serializer.Deserialize(e.EventJson),
                })
                                              .ToList();

                actual.Should().HaveCount(events.Length);

                IEnumerable <object> expected = events.Select(e => new
                {
                    AggregateType = typeof(FakeUser).FullName,
                    e.Version,
                    EventType = e.GetType().FullName,
                    Payload   = e,
                });

                actual.ShouldAllBeEquivalentTo(expected);
            }
        }
        public async Task SaveEvents_saves_events_correctly()
        {
            // Arrange
            FakeUserCreated     created         = _fixture.Create <FakeUserCreated>();
            FakeUsernameChanged usernameChanged = _fixture.Create <FakeUsernameChanged>();
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(_userId, events);
            string operationId   = _fixture.Create <string>();
            var    correlationId = Guid.NewGuid();
            string contributor   = _fixture.Create <string>();

            // Act
            await _sut.SaveEvents <FakeUser>(events, operationId, correlationId, contributor);

            // Asseert
            using (var db = new DataContext())
            {
                IEnumerable <object> actual = db
                                              .PersistentEvents
                                              .Where(e => e.AggregateId == _userId)
                                              .OrderBy(e => e.Version)
                                              .AsEnumerable()
                                              .Select(e => new
                {
                    e.Version,
                    e.EventType,
                    e.OperationId,
                    e.CorrelationId,
                    e.Contributor,
                    Payload = _serializer.Deserialize(e.EventJson),
                })
                                              .ToList();

                actual.Should().HaveCount(events.Length);

                IEnumerable <object> expected = events.Select(e => new
                {
                    e.Version,
                    EventType     = e.GetType().FullName,
                    OperationId   = operationId,
                    CorrelationId = correlationId,
                    Contributor   = contributor,
                    Payload       = e,
                });

                actual.ShouldAllBeEquivalentTo(expected);
            }
        }
Ejemplo n.º 16
0
        public async Task SaveEvents_commits_once(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(userId, events);
            var sut = new SqlEventStore(
                () => mockDbContext,
                new JsonMessageSerializer());

            await sut.SaveEvents <FakeUser>(events);

            Mock.Get(mockDbContext).Verify(
                x => x.SaveChangesAsync(CancellationToken.None), Times.Once());
        }
Ejemplo n.º 17
0
        public async Task LoadEvents_restores_all_events_correctly(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(userId, events);
            await sut.SaveEvents <FakeUser>(events);

            // Act
            IEnumerable <IDomainEvent> actual = await sut.LoadEvents <FakeUser>(userId);

            // Assert
            actual.ShouldAllBeEquivalentTo(events);
        }
        public async Task PublishPendingEvents_sends_events(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            var sourceId = Guid.NewGuid();

            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(sourceId, events);

            var envelopes = new List <Envelope>();

            using (var db = new DataContext())
            {
                foreach (DomainEvent e in events)
                {
                    var envelope = new Envelope(e);
                    envelopes.Add(envelope);
                    db.PendingEvents.Add(PendingEvent.FromEnvelope(envelope, serializer));
                }
                await db.SaveChangesAsync();
            }

            List <Envelope> batch = null;

            Mock.Get(messageBus)
            .Setup(
                x =>
                x.SendBatch(
                    It.IsAny <IEnumerable <Envelope> >(),
                    It.IsAny <CancellationToken>()))
            .Callback <IEnumerable <Envelope>, CancellationToken>((b, t) => batch = b.ToList())
            .Returns(Task.FromResult(true));

            // Act
            await sut.PublishPendingEvents(sourceId, CancellationToken.None);

            // Assert
            Mock.Get(messageBus).Verify(
                x =>
                x.SendBatch(
                    It.IsAny <IEnumerable <Envelope> >(),
                    CancellationToken.None),
                Times.Once());
            batch.ShouldAllBeEquivalentTo(envelopes, opts => opts.RespectingRuntimeTypes());
        }
        public async Task SaveEvents_saves_pending_events_correctly()
        {
            // Arrange
            FakeUserCreated     created         = _fixture.Create <FakeUserCreated>();
            FakeUsernameChanged usernameChanged = _fixture.Create <FakeUsernameChanged>();
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(_userId, events);
            string operationId   = _fixture.Create <string>();
            var    correlationId = Guid.NewGuid();
            string contributor   = _fixture.Create <string>();

            // Act
            await _sut.SaveEvents <FakeUser>(events, operationId, correlationId, contributor);

            // Asseert
            using (var db = new DataContext())
            {
                var pendingEvents = db
                                    .PendingEvents
                                    .Where(e => e.AggregateId == _userId)
                                    .OrderBy(e => e.Version)
                                    .ToList();

                foreach (var t in pendingEvents.Zip(events, (pending, source) =>
                                                    new { Pending = pending, Source = source }))
                {
                    var actual = new
                    {
                        t.Pending.Version,
                        t.Pending.OperationId,
                        t.Pending.CorrelationId,
                        t.Pending.Contributor,
                        Message = _serializer.Deserialize(t.Pending.EventJson),
                    };
                    actual.ShouldBeEquivalentTo(new
                    {
                        t.Source.Version,
                        OperationId   = operationId,
                        CorrelationId = correlationId,
                        Contributor   = contributor,
                        Message       = t.Source,
                    },
                                                opts => opts.RespectingRuntimeTypes());
                }
            }
        }
Ejemplo n.º 20
0
        public async Task SaveEvents_throws_DuplicateCorrelationException_if_correlation_duplicate(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged,
            Guid correlationId)
        {
            RaiseEvents(userId, created, usernameChanged);
            await sut.SaveEvents <FakeUser>(new[] { created }, correlationId);

            Func <Task> action = () => sut.SaveEvents <FakeUser>(new[] { usernameChanged }, correlationId);

            action.ShouldThrow <DuplicateCorrelationException>().Where(
                x =>
                x.SourceType == typeof(FakeUser) &&
                x.SourceId == userId &&
                x.CorrelationId == correlationId &&
                x.InnerException is DbUpdateException);
        }
        public async Task LoadEvents_restores_events_after_specified_version_correctly()
        {
            // Arrange
            FakeUserCreated     created         = _fixture.Create <FakeUserCreated>();
            FakeUsernameChanged usernameChanged = _fixture.Create <FakeUsernameChanged>();
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(_userId, events);
            await _sut.SaveEvents <FakeUser>(events);

            // Act
            IEnumerable <IDomainEvent> actual =
                await _sut.LoadEvents <FakeUser>(_userId, 1);

            // Assert
            actual.ShouldAllBeEquivalentTo(events.Skip(1));
        }
        public async Task SaveEvents_throws_DuplicateCorrelationException_if_correlation_duplicate()
        {
            FakeUserCreated     created         = _fixture.Create <FakeUserCreated>();
            FakeUsernameChanged usernameChanged = _fixture.Create <FakeUsernameChanged>();

            RaiseEvents(_userId, created, usernameChanged);
            var correlationId = Guid.NewGuid();
            await _sut.SaveEvents <FakeUser>(new[] { created }, correlationId : correlationId);

            Func <Task> action = () =>
                                 _sut.SaveEvents <FakeUser>(new[] { usernameChanged }, correlationId: correlationId);

            action.ShouldThrow <DuplicateCorrelationException>().Where(
                x =>
                x.SourceType == typeof(FakeUser) &&
                x.SourceId == _userId &&
                x.CorrelationId == correlationId &&
                x.InnerException is DbUpdateException);
        }
        public async Task SaveEvents_sets_message_properties_correctly()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();
            var events          = new DomainEvent[] { created, usernameChanged };

            events.Raise(userId);

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            await sut.SaveEvents <FakeUser>(
                events,
                correlationId : Guid.NewGuid(),
                contributor : Guid.NewGuid().ToString());

            // Asseert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                IEnumerable <object> expected = db
                                                .PendingEvents
                                                .Where(e => e.AggregateId == userId)
                                                .OrderBy(e => e.Version)
                                                .AsEnumerable()
                                                .Select(e => new { e.MessageId, e.CorrelationId, e.Contributor })
                                                .ToList();

                IEnumerable <object> actual = db
                                              .PersistentEvents
                                              .Where(e => e.AggregateId == userId)
                                              .OrderBy(e => e.Version)
                                              .AsEnumerable()
                                              .Select(e => new { e.MessageId, e.CorrelationId, e.Contributor })
                                              .ToList();

                actual.ShouldAllBeEquivalentTo(expected);
            }
        }
Ejemplo n.º 24
0
        public async Task FlushPendingEvents_sends_events_correctly()
        {
            // Arrange
            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();
            var sourceId        = Guid.NewGuid();

            var events = new DomainEvent[] { created, usernameChanged };

            events.Raise(sourceId);

            var envelopes = new List <Envelope>();

            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                var serializer = new JsonMessageSerializer();
                foreach (DomainEvent e in events)
                {
                    var envelope = new Envelope(
                        messageId: Guid.NewGuid(),
                        correlationId: Guid.NewGuid(),
                        contributor: Guid.NewGuid().ToString(),
                        message: e);
                    envelopes.Add(envelope);
                    db.PendingEvents.Add(PendingEvent.FromEnvelope <FakeUser>(envelope, serializer));
                }

                await db.SaveChangesAsync();
            }

            var messageBus = new MessageBus();

            var sut = new SqlEventPublisher(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer(),
                messageBus);

            // Act
            await sut.FlushPendingEvents <FakeUser>(sourceId, CancellationToken.None);

            // Assert
            messageBus.Sent.ShouldAllBeEquivalentTo(envelopes, opts => opts.RespectingRuntimeTypes());
        }
Ejemplo n.º 25
0
        public async Task FlushPendingEvents_deletes_pending_events()
        {
            // Arrange
            var sourceId = Guid.NewGuid();

            var created         = new FakeUserCreated();
            var usernameChanged = new FakeUsernameChanged();
            var events          = new DomainEvent[] { created, usernameChanged };

            events.Raise(sourceId);

            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                var serializer = new JsonMessageSerializer();
                foreach (DomainEvent e in events)
                {
                    var envelope = new Envelope(e);
                    db.PendingEvents.Add(PendingEvent.FromEnvelope <FakeUser>(envelope, serializer));
                }

                await db.SaveChangesAsync();
            }

            var sut = new SqlEventPublisher(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer(),
                Mock.Of <IMessageBus>());

            // Act
            await sut.FlushPendingEvents <FakeUser>(sourceId);

            // Assert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                bool actual = await db
                              .PendingEvents
                              .Where(e => e.AggregateId == sourceId)
                              .AnyAsync();

                actual.Should().BeFalse();
            }
        }
Ejemplo n.º 26
0
        public async Task SaveEvents_saves_pending_events_correctly(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged,
            Guid correlationId)
        {
            // Arrange
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(userId, events);

            // Act
            await sut.SaveEvents <FakeUser>(events, correlationId);

            // Asseert
            using (var db = new DataContext())
            {
                List <PendingEvent> pendingEvents = db
                                                    .PendingEvents
                                                    .Where(e => e.AggregateId == userId)
                                                    .OrderBy(e => e.Version)
                                                    .ToList();

                foreach (var t in pendingEvents.Zip(events, (pending, source) =>
                                                    new { Pending = pending, Source = source }))
                {
                    var actual = new
                    {
                        t.Pending.Version,
                        t.Pending.CorrelationId,
                        Message = serializer.Deserialize(t.Pending.EventJson)
                    };
                    actual.ShouldBeEquivalentTo(new
                    {
                        t.Source.Version,
                        CorrelationId = correlationId,
                        Message       = t.Source
                    },
                                                opts => opts.RespectingRuntimeTypes());
                }
            }
        }
Ejemplo n.º 27
0
        public async Task SaveEvents_saves_events_correctly(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            var events = new DomainEvent[] { created, usernameChanged };

            RaiseEvents(userId, events);

            // Act
            await sut.SaveEvents <FakeUser>(events);

            // Asseert
            using (var db = new DataContext())
            {
                IEnumerable <object> actual = db
                                              .PersistentEvents
                                              .Where(e => e.AggregateId == userId)
                                              .OrderBy(e => e.Version)
                                              .AsEnumerable()
                                              .Select(e => new
                {
                    e.Version,
                    e.EventType,
                    Payload = serializer.Deserialize(e.EventJson)
                })
                                              .ToList();

                actual.Should().HaveCount(events.Length);

                IEnumerable <object> expected = events.Select(e => new
                {
                    Version   = e.Version,
                    EventType = e.GetType().FullName,
                    Payload   = e
                });

                actual.ShouldAllBeEquivalentTo(expected);
            }
        }
        public async Task SaveEvents_updates_Aggregate_correctly_for_existing_aggregate_id()
        {
            // Arrange
            var userId = Guid.NewGuid();

            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                var aggregate = new Aggregate
                {
                    AggregateId   = userId,
                    AggregateType = typeof(FakeUser).FullName,
                    Version       = 1,
                };
                db.Aggregates.Add(aggregate);
                await db.SaveChangesAsync();
            }

            var usernameChanged = new FakeUsernameChanged();

            usernameChanged.Raise(userId, 1);

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            await sut.SaveEvents <FakeUser>(new[] { usernameChanged });

            // Assert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                Aggregate actual = await db
                                   .Aggregates
                                   .Where(a => a.AggregateId == userId)
                                   .SingleOrDefaultAsync();

                actual.Version.Should().Be(usernameChanged.Version);
            }
        }
Ejemplo n.º 29
0
        public void SaveEvents_fails_if_events_not_have_same_source_id(
            FakeUserCreated created,
            FakeUsernameChanged usernameChanged)
        {
            // Arrange
            created.SourceId = userId;
            created.Version  = 1;
            created.RaisedAt = DateTimeOffset.Now;

            usernameChanged.SourceId = Guid.NewGuid();
            usernameChanged.Version  = 2;
            usernameChanged.RaisedAt = DateTimeOffset.Now;

            var events = new DomainEvent[] { created, usernameChanged };

            // Act
            Func <Task> action = () => sut.SaveEvents <FakeUser>(events);

            // Assert
            action.ShouldThrow <ArgumentException>()
            .Where(x => x.ParamName == "events");
        }
        public async Task SaveEvents_removes_existing_UniqueIndexedProperty_if_property_value_is_null()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            var created = new FakeUserCreated();

            created.Raise(userId);
            await sut.SaveEvents <FakeUser>(new[] { created });

            var usernameChanged = new FakeUsernameChanged {
                Username = null
            };

            usernameChanged.Raise(userId, 1);

            // Act
            await sut.SaveEvents <FakeUser>(new[] { usernameChanged });

            // Assert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                UniqueIndexedProperty actual = await db
                                               .UniqueIndexedProperties
                                               .Where(
                    p =>
                    p.AggregateType == typeof(FakeUser).FullName &&
                    p.PropertyName == nameof(FakeUserCreated.Username) &&
                    p.PropertyValue == created.Username)
                                               .SingleOrDefaultAsync();

                actual.Should().BeNull();
            }
        }