示例#1
0
        public void GivenPopulatedEventStore_WhenLoadingAggregate_ThenAggregateVersionShouldReflectStoredEvents()
        {
            // Arrange
            var eventStore    = new InMemoryEventStore();
            var userId        = Guid.NewGuid();
            var latestVersion = Guid.NewGuid();

            eventStore.Store(
                userId,
                new object[]
            {
                new UserRegistered(userId),
                new UserChangedPassword("newpassword"),
                new UserChangedPassword("newnewpassword")
                {
                    Version = latestVersion
                }
            });
            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object);

            // Act
            User user = repository.Get(userId);

            // Assert
            Assert.AreEqual(latestVersion, user.BaseVersion);
        }
示例#2
0
        public void GivenExistingAggregateWithUnseenChanges_WhenSaving_ThenShouldCheckConcurrencyWithCorrectEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore(new ConsoleLogger());

            // Register and save a new user
            var user = new User();

            user.Register();
            var concurrencyMonitor = new StrictConcurrencyMonitor();
            var repository         = new EventSourcingRepository <User>(eventStore, concurrencyMonitor, _logger);

            repository.Save(user);
            var userVersion = user.Version;

            // We change password...
            var repository1 = new EventSourcingRepository <User>(eventStore, concurrencyMonitor, _logger);
            var user1       = repository1.Get(user.Id, userVersion);

            user1.ChangePassword("newpassword");

            // ...but so does someone else, who saves their changes before we have a chance to save ours...
            var repository2 = new EventSourcingRepository <User>(eventStore, concurrencyMonitor, _logger);
            var user2       = repository.Get(user.Id, userVersion);

            user2.ChangePassword("newpassword");
            repository2.Save(user2);

            // ...so we should get a concurrency exception when we try to save
            Assert.Throws <ConcurrencyConflictsDetectedException>(() => repository1.Save(user1));
        }
示例#3
0
        public void GivenExistingAggregateWithUnseenChanges_WhenSaving_ThenShouldCheckConcurrencyWithCorrectEvents()
        {
            // Arrange
            var userId     = Guid.NewGuid();
            var eventStore = new InMemoryEventStore();

            eventStore.Store(userId, new UserRegistered(userId));

            var concurrencyMonitor = new Mock <IConcurrencyMonitor>();
            var repository         = new EventSourcingRepository <User>(eventStore, concurrencyMonitor.Object);
            var user = repository.Get(userId);

            // Now another user changes the password before we get chance to save our changes:
            eventStore.Store(userId, new UserChangedPassword("adifferentpassword"));

            user.ChangePassword("newpassword");

            // Act
            repository.Save(user);

            // Assert
            concurrencyMonitor.Verify(
                monitor =>
                monitor.CheckForConflicts(
                    It.Is <IEnumerable <object> >(
                        unseenEvents => (unseenEvents.Single() as UserChangedPassword).NewPassword == "adifferentpassword"),
                    It.Is <IEnumerable <object> >(
                        uncommittedEvents => (uncommittedEvents.Single() as UserChangedPassword).NewPassword == "newpassword")));
        }
        public void SetUp()
        {
            var eventStore = new InMemoryEventStore();
            var repository = new EventSourcingRepository <TEntity>(eventStore, new StrictConcurrencyMonitor());
            var eventBus   = new FakeEventBus();

            Context = new TestingMessageHandlerContext <TEntity>(repository, eventBus);
        }
示例#5
0
        public void GivenAggregateWithUncommittedEvents_WhenSaving_ThenUncommittedEventsShouldBeAccepted()
        {
            // Arrange
            var user = new User();
            user.Register();
            var repository = new EventSourcingRepository<User>(new InMemoryEventStore(), new Mock<IConcurrencyMonitor>().Object);

            // Act
            repository.Save(user);

            // Assert
            CollectionAssert.IsEmpty(user.GetUncommittedEvents());
        }
示例#6
0
        public void GivenNewAggreateWithNoEvents_WhenSaving_ThenShouldNotBotherCheckingConcurrency()
        {
            // Arrange
            var user = new User();
            var concurrencyMonitor = new Mock <IConcurrencyMonitor>();
            var repository         = new EventSourcingRepository <User>(new InMemoryEventStore(), concurrencyMonitor.Object);

            // Act
            repository.Save(user);

            // Assert
            concurrencyMonitor.Verify(monitor => monitor.CheckForConflicts(It.IsAny <IEnumerable <object> >(), It.IsAny <IEnumerable <object> >()), Times.Never());
        }
示例#7
0
        public void GivenAggregateWithUncommittedEvents_WhenSaving_ThenUncommittedEventsShouldBeAccepted()
        {
            // Arrange
            var user = new User();

            user.Register();
            var repository = new EventSourcingRepository <User>(new InMemoryEventStore(), new Mock <IConcurrencyMonitor>().Object);

            // Act
            repository.Save(user);

            // Assert
            CollectionAssert.IsEmpty(user.GetUncommittedEvents());
        }
示例#8
0
        public void GivenAggregateWithNoUncommittedEvents_WhenSaved_ThenEventStoreShouldContainNoAdditionalEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var repository = new EventSourcingRepository<User>(eventStore, new Mock<IConcurrencyMonitor>().Object);
            var user = new User();

            var expectedEvents = Enumerable.Empty<object>();

            // Act
            repository.Save(user);

            // Assert
            CollectionAssertAreJsonEqual(expectedEvents, eventStore.Events);
        }
示例#9
0
        public void GivenAggregateWithNoUncommittedEvents_WhenSaved_ThenEventStoreShouldContainNoAdditionalEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object);
            var user       = new User();

            var expectedEvents = Enumerable.Empty <object>();

            // Act
            repository.Save(user);

            // Assert
            CollectionAssertAreJsonEqual(expectedEvents, eventStore.Events);
        }
示例#10
0
        public void GivenAggregateWithUncommittedEvents_WhenSaved_ThenEventStoreShouldContainThoseEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            IRepository<User> repository = new EventSourcingRepository<User>(eventStore, new Mock<IConcurrencyMonitor>().Object);
            var user = new User();
            user.Register();

            var expectedEvents = new object[] { new UserRegistered(user.Id) };

            // Act
            repository.Save(user);

            // Assert
            CollectionAssertAreJsonEqual(expectedEvents, eventStore.Events);
        }
示例#11
0
        public void GivenAggregateWithUncommittedEvents_WhenSaved_ThenEventStoreShouldContainThoseEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            IRepository <User> repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object);
            var user = new User();

            user.Register();

            var expectedEvents = new object[] { new UserRegistered(user.Id) };

            // Act
            repository.Save(user);

            // Assert
            CollectionAssertAreJsonEqual(expectedEvents, eventStore.Events);
        }
示例#12
0
        public EventSourcingRepositoryWithSqlServerTests(ITestOutputHelper output)
        {
            this.output       = output;
            this.mediatorMock = new Mock <IMediator>();
            this.mediatorMock.Setup(x => x.Publish(It.IsAny <DomainEventBase <Guid> >(), It.IsAny <CancellationToken>())).Returns(It.IsAny <Task>());
            this.connection = EventStoreConnection.Create(
                ConnectionSettings.Create()
                .EnableVerboseLogging()
                .UseConsoleLogger()
                .DisableTls()
                .Build(),
                new IPEndPoint(IPAddress.Loopback, 1113),
                "naos.test");
            this.connection.ConnectAsync().Wait();
            var eventStore = new EventStoreEventStore(this.connection);

            this.sut = new EventSourcingRepository <TestAggregate, Guid>(eventStore, this.mediatorMock.Object);
        }
示例#13
0
        public void GivenAggregateWithUncommittedEvents_WhenSaved_ThenEventStoreShouldContainThoseEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore(new ConsoleLogger());
            IRepository <User> repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object, _logger);
            var user = new User();

            user.Register();

            var expectedEvents = new object[] { new UserRegistered(user.Id) };

            // Act
            repository.Save(user);

            // Assert
            var comparisonResult = _comparer.AreEqual(expectedEvents, eventStore.GetAllEvents());

            Assert.That(comparisonResult.AreEqual, comparisonResult.InequalityReason);
        }
示例#14
0
        static async Task Main(string[] args)
        {
            var context = new SqliteDbContext();

            context.CreateTables();
            var bus = BusConfigurator.CreateBus();
            await bus.StartAsync();

            // Create or get dummy person
            var personRepository = new PersonRepository(context);
            var person           = personRepository.Find(KeywordDummy);

            if (person == null)
            {
                personRepository.Insert(new Person {
                    Name = "John", Keyword = KeywordDummy
                });
                person = personRepository.Find(KeywordDummy);
            }

            // Replay history
            var historyItems = new EventSourcingRepository(context).GetHistoryItems();
            var events       = historyItems?.Select(x => x.GetEvent()).ToList() ?? new List <PersonNameChangedEvent>();
            await bus.Publish(new BatchedPersonNameChangedEvent { Events = events });

            //foreach (var personNameChangedEvent in events)
            //    await bus.Publish(personNameChangedEvent);

            while (true)
            {
                Console.WriteLine("Enter new name");
                var newName = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(newName))
                {
                    break;
                }
                await bus.Publish(new ChangePersonNameCommand { Id = person.Id, NewName = newName });
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
            await bus.StopAsync();
        }
示例#15
0
        public void GivenAggregateWithUncommittedEvents_WhenSaved_ThenBaseVersionShouldMatchCurrentVersion()
        {
            // Arrange
            var userId = Guid.NewGuid();
            var eventStore = new InMemoryEventStore();
            var userRegistered = new UserRegistered(userId);
            eventStore.Update(userId, userRegistered);

            var repository = new EventSourcingRepository<User>(eventStore, new Mock<IConcurrencyMonitor>().Object);
            var user = repository.Get(userId);
            user.ChangePassword("newpassword");

            var currentVersion = user.GetUncommittedEvents().Cast<Event>().Last().Version;

            // Act
            repository.Save(user);

            // Assert
            Assert.AreEqual(currentVersion, user.BaseVersion, "User's base version has not been updated to match current version on successful save.");
        }
示例#16
0
        public void GivenPopulatedEventStore_WhenLoadingSpecificVersionOfAggregate_ThenRepositoryShouldRebuildThatAggregateToThatVersion()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var userId     = Guid.NewGuid();
            var events     = new object[]
            {
                new UserRegistered(userId),
                new UserChangedPassword("newpassword"),
                new UserChangedPassword("newnewpassword")
            };

            eventStore.Store(userId, events);
            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object);

            // Act
            User user = repository.Get(userId, ((Event)events[1]).Version);

            // Assert
            Assert.AreEqual(((Event)events[1]).Version, user.BaseVersion);
        }
示例#17
0
        public void GivenAggregateWithUncommittedEvents_WhenSaved_ThenBaseVersionShouldMatchCurrentVersion()
        {
            // Arrange
            var eventStore = new InMemoryEventStore(new ConsoleLogger());
            var user       = new User();

            user.Register();
            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object, _logger);

            repository.Save(user);

            user.ChangePassword("newpassword");

            var versionAfterChange = user.GetUncommittedEvents().Last().Version;

            // Act
            repository.Save(user);

            // Assert
            Assert.AreEqual(versionAfterChange, user.BaseVersion, "User's base version has not been updated to match current version on successful save.");
        }
示例#18
0
        public void GivenPopulatedEventStore_WhenLoadingSpecificVersionOfAggregate_ThenRepositoryShouldRebuildThatAggregateToThatVersion()
        {
            // Arrange
            var eventStore = new InMemoryEventStore(new ConsoleLogger());
            var userId     = Guid.NewGuid();
            var events     = new EventChain
            {
                new UserRegistered(userId),
                new UserChangedPassword("newpassword"),
                new UserChangedPassword("newnewpassword")
            };

            eventStore.Save <User>(EventStreamIdFormatter.GetStreamId <User>(userId.ToString()), 0, events);

            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object, _logger);

            // Act
            User user = repository.Get(userId, events[1].Version);

            // Assert
            Assert.AreEqual(events[1].Version, user.BaseVersion);
        }
示例#19
0
        public void GivenAggregateWithUncommittedEvents_WhenSaved_ThenBaseVersionShouldMatchCurrentVersion()
        {
            // Arrange
            var userId         = Guid.NewGuid();
            var eventStore     = new InMemoryEventStore();
            var userRegistered = new UserRegistered(userId);

            eventStore.Store(userId, userRegistered);

            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object);
            var user       = repository.Get(userId);

            user.ChangePassword("newpassword");

            var currentVersion = user.GetUncommittedEvents().Cast <Event>().Last().Version;

            // Act
            repository.Save(user);

            // Assert
            Assert.AreEqual(currentVersion, user.BaseVersion, "User's base version has not been updated to match current version on successful save.");
        }
示例#20
0
        public void GivenPopulatedEventStore_WhenLoadingAggregate_ThenRepositoryShouldRebuildThatAggregate()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var userId     = Guid.NewGuid();

            eventStore.Store(
                userId,
                new object[]
            {
                new UserRegistered(userId),
                new UserChangedPassword("newpassword"),
                new UserChangedPassword("newnewpassword")
            });
            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object);

            // Act
            User user = repository.Get(userId);

            // Assert
            Assert.Throws <InvalidOperationException>(() => user.ChangePassword("newnewpassword")); // Should fail if the user's events were correctly applied
        }
示例#21
0
        public void GivenPopulatedEventStore_WhenLoadingAggregate_ThenAggregateVersionShouldReflectStoredEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore(new ConsoleLogger());
            var userId     = Guid.NewGuid();

            eventStore.Save <User>(
                EventStreamIdFormatter.GetStreamId <User>(userId.ToString()),
                EventStreamVersion.NoStream,
                new EventChain
            {
                new UserRegistered(userId),
                new UserChangedPassword("newpassword"),
                new UserChangedPassword("newnewpassword")
            });
            var repository = new EventSourcingRepository <User>(eventStore, new Mock <IConcurrencyMonitor>().Object, _logger);

            // Act
            User user = repository.Get(userId, 2);

            // Assert
            Assert.AreEqual(2, user.BaseVersion);
        }
示例#22
0
        /*
         * Commands
         */

        public async Task Consume(ConsumeContext <ChangePersonNameCommand> context)
        {
            PersonNameChangedHistoryItem FromCommandToHistoryItem(PersonNameChangedEvent eventInner)
            => new PersonNameChangedHistoryItem
            {
                UpdatedOn = DateTime.UtcNow, Payload = JsonConvert.SerializeObject(eventInner)
            };

            PersonNameChangedEvent FromCommandToEvent(ChangePersonNameCommand command)
            => new PersonNameChangedEvent
            {
                Id = command.Id, Name = command.NewName
            };

            // store history item
            var historyRepository = new EventSourcingRepository(new SqliteDbContext());
            var @event            = FromCommandToEvent(context.Message);
            var item = FromCommandToHistoryItem(@event);

            historyRepository.AddHistoryItem(item);

            await context.Publish(@event);
        }
示例#23
0
        public void GivenPopulatedEventStore_WhenLoadingAggregate_ThenRepositoryShouldRebuildThatAggregate()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var userId = Guid.NewGuid();
            eventStore.Update(
                userId,
                new object[]
                {
                    new UserRegistered(userId),
                    new UserChangedPassword("newpassword"),
                    new UserChangedPassword("newnewpassword")
                });
            var repository = new EventSourcingRepository<User>(eventStore, new Mock<IConcurrencyMonitor>().Object);

            // Act
            User user = repository.Get(userId);

            // Assert
            Assert.Throws<InvalidOperationException>(() => user.ChangePassword("newnewpassword")); // Should fail if the user's events were correctly applied
        }
示例#24
0
        public void GivenExistingAggregateWithUnseenChanges_WhenSaving_ThenShouldCheckConcurrencyWithCorrectEvents()
        {
            // Arrange
            var userId = Guid.NewGuid();
            var eventStore = new InMemoryEventStore();
            eventStore.Update(userId, new UserRegistered(userId));

            var concurrencyMonitor = new Mock<IConcurrencyMonitor>();
            var repository = new EventSourcingRepository<User>(eventStore, concurrencyMonitor.Object);
            var user = repository.Get(userId);

            // Now another user changes the password before we get chance to save our changes:
            eventStore.Update(userId, new UserChangedPassword("adifferentpassword"));

            user.ChangePassword("newpassword");

            // Act
            repository.Save(user);

            // Assert
            concurrencyMonitor.Verify(
                monitor =>
                monitor.CheckForConflicts(
                    It.Is<IEnumerable<object>>(
                        unseenEvents => (unseenEvents.Single() as UserChangedPassword).NewPassword == "adifferentpassword"),
                    It.Is<IEnumerable<object>>(
                        uncommittedEvents => (uncommittedEvents.Single() as UserChangedPassword).NewPassword == "newpassword")));
        }
示例#25
0
        public void GivenPopulatedEventStore_WhenLoadingAggregate_ThenAggregateVersionShouldReflectStoredEvents()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var userId = Guid.NewGuid();
            var latestVersion = Guid.NewGuid();
            eventStore.Update(
                userId,
                new object[]
                {
                    new UserRegistered(userId),
                    new UserChangedPassword("newpassword"),
                    new UserChangedPassword("newnewpassword") { Version = latestVersion }
                });
            var repository = new EventSourcingRepository<User>(eventStore, new Mock<IConcurrencyMonitor>().Object);

            // Act
            User user = repository.Get(userId);

            // Assert
            Assert.AreEqual(latestVersion, user.BaseVersion);
        }
示例#26
0
        public void GivenNewAggreateWithNoEvents_WhenSaving_ThenShouldNotBotherCheckingConcurrency()
        {
            // Arrange
            var user = new User();
            var concurrencyMonitor = new Mock<IConcurrencyMonitor>();
            var repository = new EventSourcingRepository<User>(new InMemoryEventStore(), concurrencyMonitor.Object);

            // Act
            repository.Save(user);

            // Assert
            concurrencyMonitor.Verify(monitor => monitor.CheckForConflicts(It.IsAny<IEnumerable<object>>(), It.IsAny<IEnumerable<object>>()), Times.Never());
        }
示例#27
0
        public void GivenPopulatedEventStore_WhenLoadingSpecificVersionOfAggregate_ThenRepositoryShouldRebuildThatAggregateToThatVersion()
        {
            // Arrange
            var eventStore = new InMemoryEventStore();
            var userId = Guid.NewGuid();
            var events = new object[]
            {
                new UserRegistered(userId),
                new UserChangedPassword("newpassword"),
                new UserChangedPassword("newnewpassword")
            };
            eventStore.Update(userId, events);
            var repository = new EventSourcingRepository<User>(eventStore, new Mock<IConcurrencyMonitor>().Object);

            // Act
            User user = repository.Get(userId, ((Event)events[1]).Version);

            // Assert
            Assert.AreEqual(((Event)events[1]).Version, user.BaseVersion);
        }