Beispiel #1
0
        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));
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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;
        }
Beispiel #5
0
        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();
        }
Beispiel #11
0
        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");
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        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);
        }