public async Task Access_metadata_from_all_emitted_events() { // Arrange var snapshotStrategy = CreateSnapshotStrategy(); var eventsMetadataService = new EventsMetadataService(); var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, eventsMetadataService); var stubAggregate = StubSnapshotAggregate.Create("Snap"); stubAggregate.AddEntity("Child 1"); stubAggregate.AddEntity("Child 2"); await session.AddAsync(stubAggregate).ConfigureAwait(false); // Act await session.SaveChangesAsync().ConfigureAwait(false); // Assert var eventsWithMetadata = eventsMetadataService.GetEvents().ToList(); eventsWithMetadata.Count().Should().Be(3); eventsWithMetadata[0].Metadata.GetValue(MetadataKeys.EventName).Should().Be("StubCreated"); eventsWithMetadata[1].Metadata.GetValue(MetadataKeys.EventName).Should().Be(nameof(ChildCreatedEvent)); eventsWithMetadata[2].Metadata.GetValue(MetadataKeys.EventName).Should().Be(nameof(ChildCreatedEvent)); }
public async Task Should_throws_exception_When_aggregate_version_is_wrong() { var stores = new InMemoryStores(); // create first session instance var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, null, null); var stubAggregate1 = StubAggregate.Create("Walter White"); await session.AddAsync(stubAggregate1).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); stubAggregate1.ChangeName("Going to Version 2. Expected Version 1."); // create second session instance to getting clear tracking session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, null, null); var stubAggregate2 = await session.GetByIdAsync <StubAggregate>(stubAggregate1.Id).ConfigureAwait(false); stubAggregate2.ChangeName("Going to Version 2"); await session.AddAsync(stubAggregate2).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); Func <Task> wrongVersion = async() => await session.AddAsync(stubAggregate1); wrongVersion.ShouldThrowExactly <ExpectedVersionException <StubAggregate> >().And.Aggregate.Should().Be(stubAggregate1); }
public async Task When_call_SaveChanges_Should_store_the_snapshot() { // Arrange var snapshotStrategy = CreateSnapshotStrategy(); var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var stubAggregate = StubSnapshotAggregate.Create("Snap"); stubAggregate.AddEntity("Child 1"); stubAggregate.AddEntity("Child 2"); await session.AddAsync(stubAggregate).ConfigureAwait(false); // Act await session.SaveChangesAsync().ConfigureAwait(false); // Assert var committedSnapshot = stores.Snapshots.First(e => e.AggregateId == stubAggregate.Id); committedSnapshot.Should().NotBeNull(); var snapshotClrType = committedSnapshot.Metadata.GetValue(MetadataKeys.SnapshotClrType, value => value.ToString()); Type.GetType(snapshotClrType).Name.Should().Be(typeof(StubSnapshotAggregateSnapshot).Name); var snapshot = (StubSnapshotAggregateSnapshot)committedSnapshot.Data; snapshot.Name.Should().Be(stubAggregate.Name); snapshot.SimpleEntities.Count.Should().Be(stubAggregate.Entities.Count); }
public EventStoreTests() { _stores = new InMemoryStores(); var mockLogger = new Mock <ILogger>(); mockLogger.Setup(e => e.IsEnabled(It.IsAny <LogLevel>())).Returns(true); mockLogger.Setup(e => e.Log(It.IsAny <LogLevel>(), It.IsAny <string>(), It.IsAny <Exception>())); var mockLoggerFactory = new Mock <ILoggerFactory>(); mockLoggerFactory.Setup(e => e.Create(It.IsAny <string>())).Returns(mockLogger.Object); _mockEventPublisher = new Mock <IEventPublisher>(); _mockEventPublisher.Setup(e => e.PublishAsync(It.IsAny <IEnumerable <IDomainEvent> >())).Returns(Task.CompletedTask); var session = new Session(mockLoggerFactory.Object, _stores, _stores.EventStore, _stores.SnapshotStore, _mockEventPublisher.Object); _repository = new Repository(mockLoggerFactory.Object, session); var unitOfWorkMock = new Mock <IUnitOfWork>(); unitOfWorkMock.Setup(e => e.CommitAsync()) .Callback(async() => { await session.SaveChangesAsync().ConfigureAwait(false); }) .Returns(Task.CompletedTask); _unitOfWork = unitOfWorkMock.Object; }
public async Task Getting_snapshot_and_forward_events() { var snapshotStrategy = CreateSnapshotStrategy(); var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var stubAggregate = StubSnapshotAggregate.Create("Snap"); await session.AddAsync(stubAggregate).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); // Version 1 stubAggregate.ChangeName("Renamed"); stubAggregate.ChangeName("Renamed again"); // dont make snapshot snapshotStrategy = CreateSnapshotStrategy(false); session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); await session.AddAsync(stubAggregate).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); // Version 3 var stubAggregateFromSnapshot = await session.GetByIdAsync <StubSnapshotAggregate>(stubAggregate.Id).ConfigureAwait(false); stubAggregateFromSnapshot.Version.Should().Be(3); }
public async Task Should_emit_many_events() { var eventStore = new InMemoryStores(); var server = TestServerFactory(eventStore, eventStore); var response = await server.CreateRequest("/command/foo/flood/4").PostAsync(); eventStore.Events.Count.Should().Be(4); response.StatusCode.Should().Be(HttpStatusCode.OK); }
public async Task Should_create_foo() { // Arrange var stores = new InMemoryStores(); var server = TestServerFactory(stores, stores); var response = await server.CreateRequest("/command/foo").PostAsync(); var result = await response.Content.ReadAsStringAsync(); var aggregateId = ExtractAggregateIdFromResponseContent(result); stores.Events.Count(e => e.AggregateId == aggregateId).Should().Be(1); }
private async Task <Session> ArrangeSessionAsync <TAggregate>(Guid aggregateId, IEventUpdateManager eventUpdateManager = null, params IDomainEvent[] arrangeEvents) where TAggregate : Aggregate, new() { var metadataProviders = new IMetadataProvider[] { new AggregateTypeMetadataProvider(), new EventTypeMetadataProvider(), new CorrelationIdMetadataProvider() }; var loggerFactory = new NoopLoggerFactory(); var eventPublisher = new EventPublisher(new StubEventRouter()); var stores = new InMemoryStores(); var session = new Session(loggerFactory, stores, stores.EventStore, stores.SnapshotStore, eventPublisher, eventUpdateManager: eventUpdateManager); var aggregate = (TAggregate)Activator.CreateInstance(typeof(TAggregate), args: aggregateId); var serializedEvents = arrangeEvents.Select((e, index) => { index++; var eventVersion = aggregate.Version + index; var metadata = metadataProviders.SelectMany(md => md.Provide(aggregate, e, MetadataCollection.Empty)).Concat(new[] { new KeyValuePair <string, object>(MetadataKeys.EventId, Guid.NewGuid()), new KeyValuePair <string, object>(MetadataKeys.EventVersion, eventVersion) }); return(new UncommittedEvent(aggregate, e, eventVersion) { Metadata = new MetadataCollection(metadata) }); }); stores.BeginTransaction(); await stores.EventStore.AppendAsync(serializedEvents); await stores.CommitAsync(); return(session); }
public async Task Verify_custom_metadata() { // Arrange var eventStore = new InMemoryStores(); var eventsMetadataService = new EventsMetadataService(); var server = TestServerFactory(eventStore, eventStore, eventsMetadataService); var response = await server.CreateRequest("/command/foo").PostAsync(); var eventsWithMetadata = eventsMetadataService.GetEvents().ToList(); eventsWithMetadata.Count().Should().Be(1); var fakeUser = eventsWithMetadata[0].Metadata.GetValue(FakeUserMetadataProvider.MetadataKey, e => (User)e); fakeUser.Name.Should().Be("Xomano"); fakeUser.UserCode.Should().Be(123); }
public async Task Should_do_something() { var stores = new InMemoryStores(); var server = TestServerFactory(stores, stores); var response = await server.CreateRequest("/command/foo").PostAsync(); var result = await response.Content.ReadAsStringAsync(); var aggregateId = ExtractAggregateIdFromResponseContent(result); response = await server.CreateRequest($"/command/foo/{aggregateId}/doSomething").PostAsync(); response.StatusCode.Should().Be(HttpStatusCode.OK); aggregateId.Should().NotBeEmpty(); }
public async Task Should_publish_in_correct_order() { var events = new List <IDomainEvent>(); var stores = new InMemoryStores(); _eventPublisherMock.Setup(e => e.PublishAsync(It.IsAny <IEnumerable <IDomainEvent> >())).Callback <IEnumerable <IDomainEvent> >(evts => events.AddRange(evts)).Returns(Task.CompletedTask); _eventPublisherMock.Setup(e => e.CommitAsync()).Returns(Task.CompletedTask); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, null, null); var stubAggregate1 = StubAggregate.Create("Walter White"); var stubAggregate2 = StubAggregate.Create("Heinsenberg"); stubAggregate1.ChangeName("Saul Goodman"); stubAggregate2.Relationship(stubAggregate1.Id); stubAggregate1.ChangeName("Jesse Pinkman"); await session.AddAsync(stubAggregate1).ConfigureAwait(false); await session.AddAsync(stubAggregate2).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); events[0].Should().BeOfType <Event <StubAggregateCreatedEvent> >().Which.InnerEvent.AggregateId.Should().Be(stubAggregate1.Id); events[0].Should().BeOfType <Event <StubAggregateCreatedEvent> >().Which.InnerEvent.Name.Should().Be("Walter White"); events[1].Should().BeOfType <Event <StubAggregateCreatedEvent> >().Which.InnerEvent.AggregateId.Should().Be(stubAggregate2.Id); events[1].Should().BeOfType <Event <StubAggregateCreatedEvent> >().Which.InnerEvent.Name.Should().Be("Heinsenberg"); events[2].Should().BeOfType <Event <NameChangedEvent> >().Which.InnerEvent.AggregateId.Should().Be(stubAggregate1.Id); events[2].Should().BeOfType <Event <NameChangedEvent> >().Which.InnerEvent.Name.Should().Be("Saul Goodman"); events[3].Should().BeOfType <Event <StubAggregateRelatedEvent> >().Which.InnerEvent.AggregateId.Should().Be(stubAggregate2.Id); events[3].Should().BeOfType <Event <StubAggregateRelatedEvent> >().Which.InnerEvent.StubAggregateId.Should().Be(stubAggregate1.Id); events[4].Should().BeOfType <Event <NameChangedEvent> >().Which.InnerEvent.AggregateId.Should().Be(stubAggregate1.Id); events[4].Should().BeOfType <Event <NameChangedEvent> >().Which.InnerEvent.Name.Should().Be("Jesse Pinkman"); }
public async Task Should_retrieve_the_aggregate_from_tracking() { var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, null, null); var stubAggregate1 = StubAggregate.Create("Walter White"); await session.AddAsync(stubAggregate1).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); stubAggregate1.ChangeName("Changes"); var stubAggregate2 = await session.GetByIdAsync <StubAggregate>(stubAggregate1.Id).ConfigureAwait(false); stubAggregate2.ChangeName("More changes"); stubAggregate1.Should().BeSameAs(stubAggregate2); }
public Task Should_throws_exception_When_aggregate_was_not_found() { var snapshotStrategy = CreateSnapshotStrategy(); var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var newId = Guid.NewGuid(); Func <Task> act = async() => { await session.GetByIdAsync <StubAggregate>(newId).ConfigureAwait(false); }; var assertion = act.ShouldThrowExactly <AggregateNotFoundException>(); assertion.Which.AggregateName.Should().Be(typeof(StubAggregate).Name); assertion.Which.AggregateId.Should().Be(newId); return(Task.CompletedTask); }
public async Task Should_create_user() { InMemoryStores stores = null; // Arrange Func <IServiceProvider, Tuple <ITransaction, ICompositeStores> > compositeStoresFactory = (c) => { stores = new InMemoryStores(c.GetService <ProjectionRebuilder>()); return(new Tuple <ITransaction, ICompositeStores>(stores, stores)); }; var client = TestServerFactory(compositeStoresFactory); var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Post, "/command/user")); var result = await response.Content.ReadAsStringAsync(); var aggregateId = ExtractAggregateIdFromResponseContent(result); stores?.Events.Count(e => e.AggregateId == aggregateId).Should().Be(1); _projections.Count().Should().Be(2); }
public async Task When_not_exists_snapshot_yet_Then_aggregate_should_be_constructed_using_your_events() { var snapshotStrategy = CreateSnapshotStrategy(false); var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var stubAggregate = StubSnapshotAggregate.Create("Snap"); stubAggregate.AddEntity("Child 1"); stubAggregate.AddEntity("Child 2"); await session.AddAsync(stubAggregate).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var aggregate = await session.GetByIdAsync <StubSnapshotAggregate>(stubAggregate.Id).ConfigureAwait(false); aggregate.Name.Should().Be(stubAggregate.Name); aggregate.Entities.Count.Should().Be(stubAggregate.Entities.Count); }
public async Task Should_update_user() { // Arrange InMemoryStores stores = null; Func <IServiceProvider, Tuple <ITransaction, ICompositeStores> > compositeStoresFactory = (c) => { stores = new InMemoryStores(c.GetService <ProjectionRebuilder>()); return(new Tuple <ITransaction, ICompositeStores>(stores, stores)); }; var client = TestServerFactory(compositeStoresFactory); var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Post, "/command/user")); var result = await response.Content.ReadAsStringAsync(); var aggregateId = ExtractAggregateIdFromResponseContent(result); // Act var json = JsonConvert.SerializeObject(new { Name = "N" }); var content = new StringContent(json, Encoding.UTF8, "application/json"); response = await client.PutAsync($"/command/user/{aggregateId}", content); result = await response.Content.ReadAsStringAsync(); // Assert stores?.Events.Count(e => e.AggregateId == aggregateId).Should().Be(2); _projections.Count().Should().Be(2); _projections.Values.SelectMany(e => e.Keys).Count(e => e.EndsWith(aggregateId.ToString())).Should().Be(2); }
public async Task Should_restore_aggregate_using_snapshot() { var snapshotStrategy = CreateSnapshotStrategy(); var stores = new InMemoryStores(); var session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var stubAggregate = StubSnapshotAggregate.Create("Snap"); stubAggregate.AddEntity("Child 1"); stubAggregate.AddEntity("Child 2"); await session.AddAsync(stubAggregate).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); session = _sessionFactory(stores, stores.EventStore, stores.SnapshotStore, _eventPublisherMock.Object, snapshotStrategy, null); var aggregate = await session.GetByIdAsync <StubSnapshotAggregate>(stubAggregate.Id).ConfigureAwait(false); aggregate.Version.Should().Be(3); aggregate.Id.Should().Be(stubAggregate.Id); }