public async Task SaveEvents_inserts_Correlation_entity_correctly() { // Arrange var userId = Guid.NewGuid(); var created = new FakeUserCreated(); var correlationId = Guid.NewGuid(); created.Raise(userId); DateTime now = DateTime.UtcNow; var sut = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); // Act await sut.SaveEvents <FakeUser>(new[] { created }, correlationId : correlationId); // Assert using (var db = new FakeEventStoreDbContext(_dbContextOptions)) { Correlation correlation = await db .Correlations .Where( c => c.AggregateType == typeof(FakeUser).FullName && c.AggregateId == userId && c.CorrelationId == correlationId) .SingleOrDefaultAsync(); correlation.Should().NotBeNull(); correlation.HandledAt.Should().BeCloseTo(now, precision: 100); } }
public async Task SaveEvents_does_not_insert_UniqueIndexedProperty_if_property_value_is_null() { // Arrange var userId = Guid.NewGuid(); var created = new FakeUserCreated { Username = null }; created.Raise(userId); var sut = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); // Act await sut.SaveEvents <FakeUser>(new DomainEvent[] { created }); // 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(); } }
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"); }
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); } }
public async Task SaveEvents_inserts_Aggregate_correctly_for_new_aggregate_id() { // Arrange var userId = Guid.NewGuid(); var created = new FakeUserCreated(); var events = new DomainEvent[] { created }; 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)) { Aggregate actual = await db .Aggregates .Where(a => a.AggregateId == userId) .SingleOrDefaultAsync(); actual.Should().NotBeNull(); actual.AggregateType.Should().Be(typeof(FakeUser).FullName); actual.Version.Should().Be(created.Version); } }
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()); } } }
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 static void ClassInitialize(TestContext context) { _dbContextOptions = new DbContextOptionsBuilder() .UseSqlServer($@"Server=(localdb)\mssqllocaldb;Database={typeof(SqlEventPublisher_specs).FullName}.Core;Trusted_Connection=True;") .Options; using (var db = new FakeEventStoreDbContext(_dbContextOptions)) { db.Database.Migrate(); db.Database.ExecuteSqlCommand("DELETE FROM Aggregates"); db.Database.ExecuteSqlCommand("DELETE FROM PersistentEvents"); db.Database.ExecuteSqlCommand("DELETE FROM PendingEvents"); db.Database.ExecuteSqlCommand("DELETE FROM UniqueIndexedProperties"); } }
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()); }
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); } }
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(); } }
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); } }
public async Task SaveEvents_fails_if_unique_indexed_property_duplicate() { // Arrange var sut = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); string duplicateUserName = Guid.NewGuid().ToString(); var macId = Guid.NewGuid(); var macCreated = new FakeUserCreated { Username = duplicateUserName }; macCreated.Raise(macId); await sut.SaveEvents <FakeUser>(new[] { macCreated }); // Act var toshId = Guid.NewGuid(); var toshCreated = new FakeUserCreated { Username = duplicateUserName }; toshCreated.Raise(toshId); Func <Task> action = () => sut.SaveEvents <FakeUser>(new[] { toshCreated }); // Assert action.ShouldThrow <Exception>(); using (var db = new FakeEventStoreDbContext(_dbContextOptions)) { IQueryable <PersistentEvent> query = from e in db.PersistentEvents where e.AggregateId == toshId select e; (await query.AnyAsync()).Should().BeFalse(); } }