public void InheritedEventHandlerTest()
        {
            string firstAggregateId  = "ar1";
            string secondAggregateId = "ar2";

            string firstCommandId  = "c1";
            string secondCommandId = "c2";


            var    item           = new StockItem("item", "123");
            string movementNumber = $"movement_{Guid.NewGuid()}";

            var eventStore = new InMemoryEventStore();

            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>()
                               .WithEventHandler <AdjustedIn, Adjustment>(e => e.EventBody.Adjustment);

            var options = new DomainOptions(DomainOption.CacheRuntimeModel);

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, options);

            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>(firstCommandId, firstCommandId, firstAggregateId, new CreateLocation(firstAggregateId)));

            var results = engine.Process(CommandFactory.Default.CreateCommand <MoveIn>(secondCommandId, secondCommandId, firstAggregateId, new MoveIn(movementNumber, firstAggregateId, item, secondAggregateId))).ToList();

            Assert.IsTrue(results.Any(r => r.EventBodyType == typeof(TransactionRecorded).FullName));
        }
        public void ProcessTwoSequentialCommandsTest()
        {
            var eventStore   = new InMemoryEventStore();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>();

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, DomainOptions.Defaults);

            var item = new StockItem("item", "123");

            var results1 = engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c1", "c1", "ar1", new CreateLocation("locationA")));
            var results2 = engine.Process(CommandFactory.Default.CreateCommand <AdjustIn>("c2", "c1", "ar1", new AdjustIn($"adjustment_{Guid.NewGuid()}", "locationA", item)));

            Assert.IsNotNull(results1.FirstOrDefault(e => e.EventBody is LocationCreated));
            Assert.IsNotNull(results2.FirstOrDefault(e => e.EventBody is AdjustedIn));
        }
        public void AggregateAndStatefulProcessEventsTest()
        {
            string firstAggregateId  = "ar1";
            string secondAggregateId = "ar2";
            string firstCommandId    = "c1";
            string secondCommandId   = "c2";
            string thirdCommandId    = "c3";
            string fourthCommandId   = "c4";
            var    item           = new StockItem("item", "123");
            string movementNumber = $"movement_{Guid.NewGuid()}";

            var eventStore = new InMemoryEventStore();

            var contextModel = new BoundedContextModel() //.WithAssemblyContaining<Location>()
                               .WithAggregateRoot <Location>()
                               .WithEventHandler <MovedOut, Movement, MoveIn>(e => e.EventBody.Movement.ToString(), c => c.Location)
                               .WithEventHandler <MovedIn, Movement>(e => e.EventBody.Movement.ToString());

            var options = new DomainOptions(DomainOption.CacheRuntimeModel);

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, options);

            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>(firstCommandId, firstCommandId, firstAggregateId, new CreateLocation(firstAggregateId)));
            engine.Process(CommandFactory.Default.CreateCommand <AdjustIn>(secondCommandId, secondCommandId, firstAggregateId, new AdjustIn($"adjustment_{Guid.NewGuid()}", firstAggregateId, item)));
            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>(thirdCommandId, thirdCommandId, secondAggregateId, new CreateLocation(secondAggregateId)));

            var results = engine.Process(CommandFactory.Default.CreateCommand <MoveOut>(fourthCommandId, fourthCommandId, firstAggregateId, new MoveOut(movementNumber, firstAggregateId, item, secondAggregateId))).ToList();

            Assert.IsTrue(results.Count == 2);

            Assert.IsInstanceOfType(results[0].EventBody, typeof(MovedOut));
            Assert.IsTrue(results[0].AggregateId == firstAggregateId);
            Assert.IsTrue(results[0].AggregateType == typeof(Location).FullName);
            Assert.IsTrue(results[0].AggregateVersion == 3);
            Assert.IsTrue(results[0].CommandId == fourthCommandId);
            Assert.IsTrue(results[0].CorrelationId == fourthCommandId);
            Assert.IsTrue(results[0].EventBodyType == typeof(MovedOut).FullName);
            Assert.IsTrue(results[0].Id == $"{firstAggregateId}\\{results[0].AggregateVersion}");

            Assert.IsInstanceOfType(results[1].EventBody, typeof(MovedIn));
            Assert.IsTrue(results[1].AggregateId == secondAggregateId);
            Assert.IsTrue(results[1].AggregateType == typeof(Location).FullName);
            Assert.IsTrue(results[1].AggregateVersion == 2);
            Assert.IsTrue(results[1].CommandId == $"{typeof(Movement).Name}\\{movementNumber}\\{1}");
            Assert.IsTrue(results[1].CorrelationId == fourthCommandId);
            Assert.IsTrue(results[1].EventBodyType == typeof(MovedIn).FullName);
            Assert.IsTrue(results[1].Id == $"{secondAggregateId}\\{results[1].AggregateVersion}");
        }
        public void ExeptionIsThrownTest()
        {
            string commandId = "c1";

            string experimentId = Guid.NewGuid().ToString();

            var eventStore = new InMemoryEventStore();

            var contextModel = new BoundedContextModel().WithAssemblyContaining <Experiment>();

            var options = new DomainOptions(DomainOption.CacheRuntimeModel);

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, options);

            Assert.ThrowsException <ApplicationException>(() => { engine.Process(CommandFactory.Default.CreateCommand <PerformBadExperiment>(commandId, commandId, experimentId, new PerformBadExperiment(true))); });
        }
        public void ProcessTwoSequentialCommandsUsingDefaultHandlersTest()
        {
            var eventStore   = new Mock <IEventStore>();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>();

            eventStore.Setup(x => x.RetrieveById(It.IsAny <string>())).Returns(new Collection <IEvent>());

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore.Object, DomainOptions.Defaults);

            var item = new StockItem("item", "123");

            var results1 = engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c1", "c1", "ar1", new CreateLocation("locationA")));
            var results2 = engine.Process(CommandFactory.Default.CreateCommand <AdjustIn>("c2", "c1", "ar1", new AdjustIn($"adjustment_{Guid.NewGuid()}", "locationA", item)));

            Assert.IsNotNull(results1.FirstOrDefault(e => e.EventBody is LocationCreated));
            Assert.IsNotNull(results2.FirstOrDefault(e => e.EventBody is AdjustedIn));
        }
        public void ExeptionIsWrappedInEventTest()
        {
            string commandId = "c1";

            string experimentId = Guid.NewGuid().ToString();

            var eventStore = new InMemoryEventStore();

            var contextModel = new BoundedContextModel().WithAssemblyContaining <Experiment>().WithExceptionEvent <BadEvent>((e) => new BadEvent(e));

            var options = new DomainOptions(DomainOption.CacheRuntimeModel);

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, options);

            var result = engine.Process(CommandFactory.Default.CreateCommand <PerformBadExperiment>(commandId, commandId, experimentId, new PerformBadExperiment(true)));

            Assert.IsNotNull(result.FirstOrDefault(e => e.EventBody is BadEvent));
        }
        public void MultipleOptionalEventsAllNullTest()
        {
            string commandId = "c1";

            string experimentId = Guid.NewGuid().ToString();

            var eventStore = new InMemoryEventStore();

            var contextModel = new BoundedContextModel().WithAssemblyContaining <Experiment>();

            var options = new DomainOptions(DomainOption.CacheRuntimeModel);

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, options);

            var results = engine.Process(CommandFactory.Default.CreateCommand <PerformExperiment>(commandId, commandId, experimentId, new PerformExperiment(false, false)));

            Assert.IsTrue(results.Count() == 0);
        }
        public void ProcessCommandUsingDefaultHandlerTest()
        {
            var commandId     = "command1";
            var correlationId = "command1";
            var aggregateId   = "location1";

            var eventStore   = new Mock <IEventStore>();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>();

            eventStore.Setup(x => x.RetrieveById(It.IsAny <string>())).Returns(new Collection <IEvent>());

            var item = new StockItem("item", "123");

            var command = CommandFactory.Default.CreateCommand <MoveIn>(commandId, correlationId, aggregateId, new MoveIn($"movement_{Guid.NewGuid()}", "locationA", item, "locationB"));

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore.Object, DomainOptions.Defaults);

            engine.Process(command);
        }
        public void ProcessCommandUsingCustomHandlerTest()
        {
            var commandId     = "command1";
            var correlationId = "command1";
            var aggregateId   = "location1";

            var contextModel = new BoundedContextModel()
                               .WithAssemblyContaining <Location>()
                               .WithCommandHandler <MoveIn, Location, MovedIn>();

            var eventStore = new InMemoryEventStore();

            var item = new StockItem("item", "123");

            var command = CommandFactory.Default.CreateCommand <MoveIn>(commandId, correlationId, aggregateId, new MoveIn($"movement_{Guid.NewGuid()}", "locationA", item, "locationB"));

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, DomainOptions.Defaults);

            engine.Process(command);
        }
        public void AggregateEventTest()
        {
            string aggregateId = "ar1";
            string commandId   = "c1";

            var eventStore   = new InMemoryEventStore();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>();

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, DomainOptions.Defaults);

            var result = engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>(commandId, commandId, aggregateId, new CreateLocation(aggregateId))).Single();

            Assert.IsInstanceOfType(result.EventBody, typeof(LocationCreated));
            Assert.IsTrue(result.AggregateId == aggregateId);
            Assert.IsTrue(result.AggregateType == typeof(Location).FullName);
            Assert.IsTrue(result.AggregateVersion == 1);
            Assert.IsTrue(result.CommandId == commandId);
            Assert.IsTrue(result.CorrelationId == commandId);
            Assert.IsTrue(result.EventBodyType == typeof(LocationCreated).FullName);
            Assert.IsTrue(result.Id == $"{aggregateId}\\{result.AggregateVersion}");
        }
        public void IocUsingUnityTest()
        {
            var unityContainer = new UnityContainer();

            unityContainer.RegisterType <Location>();
            unityContainer.RegisterType <InventoryItem>();

            var domainObjectFactory = new UnityDomainObjectFactory(unityContainer);

            var eventStore   = new Mock <IEventStore>();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>().WithDomainObjectResolver(domainObjectFactory);

            eventStore.Setup(x => x.RetrieveById(It.IsAny <string>())).Returns(new Collection <IEvent>());

            var command1 = CommandFactory.Default.CreateCommand <CreateLocation>(id: "C1", aggregateId: "Location 1", command: new CreateLocation("Location 1"));
            var command2 = CommandFactory.Default.CreateCommand <CreateInventoryItem>(id: "C2", aggregateId: "Item A", command: new CreateInventoryItem("Item A"));

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore.Object, DomainOptions.Defaults);

            engine.Process(command1);
            engine.Process(command2);
        }
        public void SimpleProcessUpdatesTwoAggregatesUsingDefaultHandlersTest()
        {
            var eventStore     = new InMemoryEventStore();
            var contextModel   = new BoundedContextModel().WithAssemblyContaining <Location>();
            var aggregateModel = new RuntimeModel(contextModel, eventStore);

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, DomainOptions.Defaults);

            var item = new StockItem("item", "123");

            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c1", "c1", "ar1", new CreateLocation("ar1")));
            engine.Process(CommandFactory.Default.CreateCommand <AdjustIn>("c2", "c1", "ar1", new AdjustIn($"adjustment_{Guid.NewGuid()}", "ar1", item)));
            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c3", "c3", "ar2", new CreateLocation("ar2")));

            var results = engine.Process(CommandFactory.Default.CreateCommand <MoveOut>("c3", "c3", "ar1", new MoveOut($"movement_{Guid.NewGuid()}", "ar1", item, "ar2")));

            var movedOutEvent = results.FirstOrDefault(e => e.EventBody is MovedOut);
            var movedInEvent  = results.FirstOrDefault(e => e.EventBody is MovedIn);

            Assert.IsNotNull(movedOutEvent);
            Assert.IsNotNull(movedInEvent);
        }
        public void CommandIsIdempotent()
        {
            string aggregateId  = "ar1";
            string commandId    = "c1";
            string adjustmentId = "adjust1";
            var    item         = new StockItem("item", "123");


            var eventStore   = new InMemoryEventStore();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>();

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, DomainOptions.Defaults);

            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c0", "c0", aggregateId, new CreateLocation(aggregateId))).Single();

            var command = CommandFactory.Default.CreateCommand <AdjustIn>(commandId, commandId, aggregateId, new AdjustIn(adjustmentId, aggregateId, item));

            var firstResults  = engine.Process(command);
            var secondResults = engine.Process(command);

            Assert.IsTrue(firstResults.Any(e => e.EventBody is AdjustedIn));
            Assert.IsFalse(secondResults.Any(e => e.EventBody is AdjustedIn));
        }
        public void IoCUsingNijectTest()
        {
            var ninjectKernel = new StandardKernel();

            ninjectKernel.Bind <Location>().To <Location>();
            ninjectKernel.Bind <InventoryItem>().To <InventoryItem>();

            var domainObjectFactory = new NinjectDomainObjectFactory(ninjectKernel);

            var eventStore   = new Mock <IEventStore>();
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>().WithDomainObjectResolver(domainObjectFactory);
            var domainModel  = new RuntimeModel(contextModel, eventStore.Object);

            eventStore.Setup(x => x.RetrieveById(It.IsAny <string>())).Returns(new Collection <IEvent>());

            var command1 = CommandFactory.Default.CreateCommand <CreateLocation>(id: "C1", aggregateId: "Location 1", command: new CreateLocation("Location 1"));
            var command2 = CommandFactory.Default.CreateCommand <CreateInventoryItem>(id: "C2", aggregateId: "Item A", command: new CreateInventoryItem("Item A"));

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore.Object, DomainOptions.Defaults);

            engine.Process(command1);
            engine.Process(command2);
        }
        public void IoCUsingCustomMethodTest()
        {
            var domainObjectResolver = new Mock <IDomainObjectResolver>();

            domainObjectResolver.Setup(x => x.New <Location>()).Returns(new Location());
            domainObjectResolver.Setup(x => x.New <InventoryItem>()).Returns(new InventoryItem());
            domainObjectResolver.Setup(x => x.New(It.Is <Type>(x => x == typeof(Location)))).Returns(new Location()).Verifiable();
            domainObjectResolver.Setup(x => x.New(It.Is <Type>(x => x == typeof(InventoryItem)))).Returns(new InventoryItem()).Verifiable();

            var eventStore   = new Mock <IEventStore>(MockBehavior.Loose);
            var contextModel = new BoundedContextModel().WithAssemblyContaining <Location>().WithDomainObjectResolver(domainObjectResolver.Object);

            eventStore.Setup(x => x.RetrieveById(It.IsAny <string>(), It.IsAny <int>())).Returns(new Collection <IEvent>());

            var command1 = CommandFactory.Default.CreateCommand <CreateLocation>(id: "C1", aggregateId: "Location 1", command: new CreateLocation("Location 1"));
            var command2 = CommandFactory.Default.CreateCommand <CreateInventoryItem>(id: "C2", aggregateId: "Item A", command: new CreateInventoryItem("Item A"));

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore.Object, DomainOptions.Defaults);

            engine.Process(command1);
            engine.Process(command2);

            domainObjectResolver.VerifyAll();
        }
        public void SimpleProcessUpdatesTwoAggregatesAndFinalEventHandlerUsingDefaultHandlersTest()
        {
            var eventStore = new InMemoryEventStore();

            var contextModel = new BoundedContextModel()
                               .WithAssemblyContaining <Location>()
                               .WithEventHandler <TestEventHandler>();

            var aggregateModel = new RuntimeModel(contextModel, eventStore);
            var item           = new StockItem("item", "123");

            items.Clear();

            var engine = DomainFactory.CreateDomainExecutionEngine(contextModel, eventStore, DomainOptions.Defaults);

            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c1", "c1", "ar1", new CreateLocation("ar1")));
            engine.Process(CommandFactory.Default.CreateCommand <AdjustIn>("c2", "c1", "ar1", new AdjustIn($"adjustment_{Guid.NewGuid()}", "ar1", item)));
            engine.Process(CommandFactory.Default.CreateCommand <CreateLocation>("c3", "c3", "ar2", new CreateLocation("ar2")));

            var results = engine.Process(CommandFactory.Default.CreateCommand <MoveOut>("c3", "c3", "ar1", new MoveOut($"movement_{Guid.NewGuid()}", "ar1", item, "ar2")));

            Assert.AreEqual(1, items.Count);
            Assert.AreEqual(item, items[0]);
        }