public void SaveEvents_fails_if_events_contains_null() { // Arrange var userId = Guid.NewGuid(); var created = new FakeUserCreated(); created.Raise(userId); var events = new DomainEvent[] { created, null }; var sut = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); // Act Func <Task> action = () => sut.SaveEvents <FakeUser>(events); // Assert action.ShouldThrow <ArgumentException>().Where(x => x.ParamName == "events"); }
public async Task SaveEvents_commits_once() { var userId = Guid.NewGuid(); var events = new DomainEvent[] { new FakeUserCreated(), new FakeUsernameChanged(), }; events.Raise(userId); var context = new DbContextSpy(_dbContextOptions); var sut = new SqlEventStore( () => context, new JsonMessageSerializer()); await sut.SaveEvents <FakeUser>(events); context.CommitCount.Should().Be(1); }
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 FlushAllPendingEvents_sends_app_pending_events() { // Arrange IEnumerable <FakeUserCreated> createdEvents = _fixture .Build <FakeUserCreated>() .With(e => e.Version, 1) .With(e => e.RaisedAt, DateTime.UtcNow) .CreateMany(); var eventStore = new SqlEventStore(() => new DataContext(), _serializer); foreach (FakeUserCreated createdEvent in createdEvents) { await eventStore.SaveEvents <FakeUser>(new[] { createdEvent }); } var sentEvents = new List <Envelope>(); Mock.Get(_messageBus) .Setup( x => x.Send( It.IsAny <IEnumerable <Envelope> >(), It.IsAny <CancellationToken>())) .Callback <IEnumerable <Envelope>, CancellationToken>((batch, t) => sentEvents.AddRange(batch)) .Returns(Task.FromResult(true)); // Act await _sut.FlushAllPendingEvents(CancellationToken.None); // Assert foreach (FakeUserCreated createdEvent in createdEvents) { sentEvents .Select(e => e.Message) .OfType <FakeUserCreated>() .Where(e => e.SourceId == createdEvent.SourceId) .Should() .ContainSingle() .Which .ShouldBeEquivalentTo(createdEvent); } }
public async Task FlushAllPendingEvents_sends_all_pending_events() { // Arrange IEnumerable <FakeUserCreated> createdEvents = new[] { new FakeUserCreated(), new FakeUserCreated(), new FakeUserCreated(), }; var eventStore = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); foreach (FakeUserCreated createdEvent in createdEvents) { createdEvent.Raise(Guid.NewGuid()); await eventStore.SaveEvents <FakeUser>( new[] { createdEvent }, correlationId : default,
public void SaveEvents_fails_if_db_context_does_not_support_transaction() { // Arrange var created = new FakeUserCreated { Version = 1 }; string databaseName = nameof(SaveEvents_fails_if_db_context_does_not_support_transaction); DbContextOptions options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName) .Options; var sut = new SqlEventStore( () => new FakeEventStoreDbContext(options), new JsonMessageSerializer()); // Act Func <Task> action = () => sut.SaveEvents <FakeUser>(new[] { created }); // Assert action.ShouldThrow <InvalidOperationException>(); }
public void SaveEvents_succeeds_if_db_context_supports_transaction() { // Arrange var created = new FakeUserCreated { Version = 1 }; string databaseName = nameof(SaveEvents_succeeds_if_db_context_supports_transaction); DbContextOptions options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName) .ConfigureWarnings(builder => builder.Ignore(InMemoryEventId.TransactionIgnoredWarning)) .Options; var sut = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); // Act Func <Task> action = () => sut.SaveEvents <FakeUser>(new[] { created }); // Assert action.ShouldNotThrow(); }
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 SqlEventStore_features(ITestOutputHelper output) { this.output = output; fixture = new Fixture().Customize(new AutoMoqCustomization()); fixture.Inject <Func <EventStoreDbContext> >(() => new DataContext()); userId = Guid.NewGuid(); serializer = new JsonMessageSerializer(); fixture.Inject(serializer); sut = fixture.Create <SqlEventStore>(); mockDbContext = Mock.Of <EventStoreDbContext>( x => x.SaveChangesAsync() == Task.FromResult(default(int))); mockDbContext.Aggregates = Mock.Of <DbSet <Aggregate> >(); Mock.Get(mockDbContext.Aggregates).SetupData(); mockDbContext.PersistentEvents = Mock.Of <DbSet <PersistentEvent> >(); Mock.Get(mockDbContext.PersistentEvents).SetupData(); mockDbContext.PendingEvents = Mock.Of <DbSet <PendingEvent> >(); Mock.Get(mockDbContext.PendingEvents).SetupData(); mockDbContext.UniqueIndexedProperties = Mock.Of <DbSet <UniqueIndexedProperty> >(); Mock.Get(mockDbContext.UniqueIndexedProperties).SetupData(); using (var db = new DataContext()) { db.Database.Log = output.WriteLine; 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 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(); } }
public async Task LoadEvents_restores_events_after_specified_version_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()); await sut.SaveEvents <FakeUser>(events); // Act IEnumerable <IDomainEvent> actual = await sut.LoadEvents <FakeUser>(userId, 1); // Assert actual.ShouldAllBeEquivalentTo(events.Skip(1)); }
public void SaveEvents_fails_if_kind_of_event_raised_time_is_not_utc(DateTimeKind dateTimeKind) { // Arrange var userId = Guid.NewGuid(); var events = new DomainEvent[] { new FakeUserCreated(), new FakeUsernameChanged(), }; events.Raise(userId); events.OrderBy(e => e.GetHashCode()).First().RaisedAt = new DateTime(DateTime.Now.Ticks, dateTimeKind); var sut = new SqlEventStore( () => new FakeEventStoreDbContext(_dbContextOptions), new JsonMessageSerializer()); // Act Func <Task> action = () => sut.SaveEvents <FakeUser>(events); // Assert action.ShouldThrow <ArgumentException>().Where(x => x.ParamName == "events"); }
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(); } }
public void TestInitialize() { _fixture = new Fixture().Customize(new AutoMoqCustomization()); _fixture.Inject <Func <EventStoreDbContext> >(() => new DataContext()); _userId = Guid.NewGuid(); _serializer = new JsonMessageSerializer(); _fixture.Inject(_serializer); _sut = _fixture.Create <SqlEventStore>(); _mockDbContext = Mock.Of <EventStoreDbContext>( x => x.SaveChangesAsync() == Task.FromResult(default(int))); _mockDbContext.Aggregates = Mock.Of <DbSet <Aggregate> >(); Mock.Get(_mockDbContext.Aggregates).SetupData(); _mockDbContext.PersistentEvents = Mock.Of <DbSet <PersistentEvent> >(); Mock.Get(_mockDbContext.PersistentEvents).SetupData(); _mockDbContext.PendingEvents = Mock.Of <DbSet <PendingEvent> >(); Mock.Get(_mockDbContext.PendingEvents).SetupData(); _mockDbContext.UniqueIndexedProperties = Mock.Of <DbSet <UniqueIndexedProperty> >(); Mock.Get(_mockDbContext.UniqueIndexedProperties).SetupData(); using (var db = new DataContext()) { db.Database.Log = m => TestContext?.WriteLine(m); db.Database.ExecuteSqlCommand("DELETE FROM Aggregates"); db.Database.ExecuteSqlCommand("DELETE FROM PersistentEvents"); db.Database.ExecuteSqlCommand("DELETE FROM PendingEvents"); db.Database.ExecuteSqlCommand("DELETE FROM UniqueIndexedProperties"); } }