public void AddingEventsWithProperExpectedVersionToExistingEventDescriptorsPopulatesDatabase()
        {
            var aggregateId = Guid.NewGuid();
            var databaseMock = new DatabaseMock<EventDescriptors>();
            var existingEvents = new EventDescriptors{ Id = aggregateId };
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 0));
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 1));
            databaseMock.Put(existingEvents);
            var initialCount = existingEvents.Count();

            var expectedVersion = existingEvents.Count() - 1;
            IConcurrencyConflictResolver conflictResolver = null;
            var newEvents = new List<Event>
            {
                new Event(),
                new Event()
            };
            
            var publisherMock = new EventPublisherMock();

            var eventStore = new EventStore(publisherMock, databaseMock);

            eventStore.SaveEvents(
                aggregateId,
                newEvents,
                expectedVersion,
                conflictResolver);

            var actual = databaseMock.Get(aggregateId.ToString());

            Assert.NotNull(actual);
            Assert.Equal(newEvents.Count + initialCount, actual.Count());
            publisherMock.AssertPublishCount<Event>(newEvents.Count());
        }
        public void JsonSerializeAndDeserialize()
        {
            var id = Guid.NewGuid();
            var expected = new EventDescriptors { Id = id };
            var events = new List<Event>
            {
                new Event1(),
                new Event2<EventConstraintBase1>(),
                new Event3<EventConstraintBase1, EventConstraintBase2>()
            };

            expected.Add(new EventDescriptor { Id = Guid.NewGuid(), EventData = events[0], Version = 0 });
            expected.Add(new EventDescriptor { Id = Guid.NewGuid(), EventData = events[1], Version = -5 });
            expected.Add(new EventDescriptor { Id = Guid.NewGuid(), EventData = events[2], Version = 1 });

            var serializerSettings = new JsonSerializerSettings
            {
                MissingMemberHandling = MissingMemberHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Ignore,
                TypeNameHandling = TypeNameHandling.All,
                ContractResolver = new PrivateMembersContractResolver(),
                DateFormatHandling = DateFormatHandling.IsoDateFormat,
                DateParseHandling = DateParseHandling.None,
                DateTimeZoneHandling = DateTimeZoneHandling.Unspecified
            };

            var intermediate = JsonConvert.SerializeObject(
                expected, 
                serializerSettings);
            var actual = (EventDescriptors)JsonConvert.DeserializeObject(
                intermediate, 
                typeof(EventDescriptors), 
                serializerSettings);

            Assert.Equal(id, actual.Id);
            Assert.Equal(expected.Count(), actual.Count());

            for (int i = 0; i < expected.Count(); i++)
            {
                Assert.Equal(expected[i].Id, actual[i].Id);
                Assert.Equal(expected[i].EventData.GetType(), actual[i].EventData.GetType());
                Assert.Equal(expected[i].Version, actual[i].Version);
            }
        }
        public void FetchingAggregateRootWhenExistsGetsProperListOfEvents()
        {
            var aggregateId = Guid.NewGuid();
            var databaseMock = new DatabaseMock<EventDescriptors>();
            var expected = new EventDescriptors { Id = aggregateId };
            expected.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 0));
            expected.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 1));
            databaseMock.Put(expected);
            var publisherMock = new EventPublisherMock();

            var eventStore = new EventStore(publisherMock, databaseMock);

            var actual = eventStore.GetEventsForAggregate(aggregateId);

            Assert.NotNull(actual);
            Assert.Equal(expected.Count(), actual.Count());
            Assert.Null(publisherMock.GetLastPublishedObject<Event>());
        }
        public async void AddingImproperlyVersionedEventsConcurrentlyWithConflictResolutionPopulatesDatabase()
        {
            var aggregateId = Guid.NewGuid();
            var databaseMock = new DatabaseMock<EventDescriptors>();
            var existingEvents = new EventDescriptors {Id = aggregateId};
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 0));
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 1));
            databaseMock.Put(existingEvents);
            var initialCount = existingEvents.Count();

            var expectedVersion = 0;
            IConcurrencyConflictResolver conflictResolver = new ConcurrencyConflictResolver();
            conflictResolver.RegisterConflictList(typeof (Event2<EventConstraint1>), new List<Type>());
            conflictResolver.RegisterConflictList(typeof (Event2<EventConstraintAnother1>), new List<Type>());
            var newEventsSource1 = new List<Event>
            {
                new Event2<EventConstraint1>()
            };
            var newEventsSource2 = new List<Event>
            {
                new Event2<EventConstraintAnother1>()
            };

            var publisherMock = new EventPublisherMock();

            var eventStore = new EventStore(publisherMock, databaseMock);

            var task1 = Task.Run(() =>
                eventStore.SaveEvents(
                    aggregateId,
                    newEventsSource1,
                    expectedVersion,
                    conflictResolver));

            var task2 = Task.Run(()=>
                    eventStore.SaveEvents(
                    aggregateId,
                    newEventsSource2,
                    expectedVersion,
                    conflictResolver));

            await Task.WhenAll(task1, task2).ConfigureAwait(false);

            var actual = databaseMock.Get(aggregateId.ToString());

            Assert.NotNull(actual);
            Assert.Equal(newEventsSource1.Count + newEventsSource2.Count + initialCount, actual.Count());
            publisherMock.AssertPublishCount<Event>(newEventsSource1.Count + newEventsSource2.Count);
        }
        public void AddingImproperlyVersionedEventsWithNoConflictResolutionExpectException()
        {
            var aggregateId = Guid.NewGuid();
            var databaseMock = new DatabaseMock<EventDescriptors>();
            var existingEvents = new EventDescriptors { Id = aggregateId };
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event1(), 0));
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event1(), 1));
            databaseMock.Put(existingEvents);

            var expectedVersion = existingEvents.Count() - 2;
            IConcurrencyConflictResolver conflictResolver = new ConcurrencyConflictResolver();
            conflictResolver.RegisterConflictList(typeof(Event1), new List<Type> {typeof(Event1)});
            var newEvents = new List<Event>
            {
                new Event1(),
                new Event1()
            };

            var publisherMock = new EventPublisherMock();

            var eventStore = new EventStore(publisherMock, databaseMock);

            Assert.Throws<EventStoreConcurrencyException>(() =>
                eventStore.SaveEvents(
                    aggregateId,
                    newEvents,
                    expectedVersion,
                    conflictResolver));
        }
        public void AddingEventsWithImproperExpectedVersionAndNullConflictResolverExpectException()
        {
            var aggregateId = Guid.NewGuid();
            var databaseMock = new DatabaseMock<EventDescriptors>();
            var existingEvents = new EventDescriptors { Id = aggregateId };
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 0));
            existingEvents.Add(new EventDescriptor(Guid.NewGuid(), new Event(), 1));
            databaseMock.Put(existingEvents);

            var expectedVersion = existingEvents.Count() - 2;
            IConcurrencyConflictResolver conflictResolver = null;
            var newEvents = new List<Event>
            {
                new Event(),
                new Event()
            };

            var publisherMock = new EventPublisherMock();

            var eventStore = new EventStore(publisherMock, databaseMock);

            Assert.Throws<EventStoreConcurrencyException>(() => 
                eventStore.SaveEvents(
                    aggregateId,
                    newEvents,
                    expectedVersion,
                    conflictResolver));
        }