public void WhenSendingAnEventThenItShouldForwardToDistributor()
        {
            var subject = new InProcessEventTransport();
            var distributor = Substitute.For<EventDistributor>(null, null, new EventTransport[0], null);
            subject.RegisterDistributor(distributor);

            var uniqueEvent = new UniqueEvent<DummyEvent>(Guid.NewGuid(), new DummyEvent(), DateTime.MinValue);

            subject.Send(uniqueEvent);

            distributor.Received().Receive(uniqueEvent);
        }
        public void WhenConsumingAnEventAndTheDecoratorCancelsThenItWillNotCallTheConsumer()
        {
            var serviceLocator = Substitute.For<IServiceLocator>();
            var eventStore = Substitute.For<EventStore>();
            var eventConsumerDecorator =
                Substitute.For<EventConsumptionDecorator<ConsumesEvent<DummyEvent>, DummyEvent>>();
            var subject = new EventDistributor(serviceLocator, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);
            var consumer = Substitute.For<ConsumesEvent<DummyEvent>>();

            serviceLocator.GetAllInstances<ConsumesEvent<DummyEvent>>().Returns(new[] {consumer});
            serviceLocator.GetInstance<EventConsumptionDecorator<ConsumesEvent<DummyEvent>, DummyEvent>>().Returns(eventConsumerDecorator);

            eventConsumerDecorator.BeforeConsumption(@event, consumer, Arg.Do<CancelEventArgs>(args => { args.Cancel = true; }));

            subject.Receive(@event);

            consumer.DidNotReceiveWithAnyArgs().Consume(null);
        }
        public void WhenConsumingAndAnExceptionIsThrownThenItWillCallTheAfterFailureDecoratorImplementationButNotTheAfterDecoratorImplementation()
        {
            var serviceLocator = Substitute.For<IServiceLocator>();
            var eventStore = Substitute.For<EventStore>();
            var eventConsumerDecorator = Substitute.For<EventConsumptionDecorator<ConsumesEvent<DummyEvent>, DummyEvent>>();
            var subject = new EventDistributor(serviceLocator, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);
            var consumer = Substitute.For<ConsumesEvent<DummyEvent>>();

            serviceLocator.GetAllInstances<ConsumesEvent<DummyEvent>>().Returns(new[] { consumer });
            serviceLocator.GetInstance<EventConsumptionDecorator<ConsumesEvent<DummyEvent>, DummyEvent>>().Returns(eventConsumerDecorator);
            var expectedException = new Exception();
            consumer.When(_ => _.Consume(@event.Event)).Do((_ => { throw expectedException; }));

            subject.Receive(@event);

            eventConsumerDecorator
                .Received()
                .AfterFailedConsumption(@event, consumer, Arg.Is<UnhandledExceptionEventArgs>(args => args.ExceptionObject == expectedException));
            eventConsumerDecorator.DidNotReceiveWithAnyArgs().AfterConsumption(null, null);
        }
        public void WhenConsumingAnEventThenItWillCallTheAfterDecoratorImplementation()
        {
            var serviceLocator = Substitute.For<IServiceLocator>();
            var eventStore = Substitute.For<EventStore>();
            var eventConsumerDecorator = Substitute.For<EventConsumptionDecorator<ConsumesEvent<DummyEvent>, DummyEvent>>();
            var subject = new EventDistributor(serviceLocator, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);
            var consumer = Substitute.For<ConsumesEvent<DummyEvent>>();

            serviceLocator.GetAllInstances<ConsumesEvent<DummyEvent>>().Returns(new[] { consumer });
            serviceLocator.GetInstance<EventConsumptionDecorator<ConsumesEvent<DummyEvent>, DummyEvent>>().Returns(eventConsumerDecorator);

            subject.Receive(@event);

            eventConsumerDecorator.Received().AfterConsumption(@event, consumer);
        }
        public void WhenReceivingAnEventThenItWillGetAllConsumersOfTheEvent()
        {
            var serviceLocator = Substitute.For<IServiceLocator>();
            var eventStore = Substitute.For<EventStore>();
            var subject = new EventDistributor(serviceLocator, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);

            eventStore.IsEventAlreadyConsumed(@event).Returns(false);
            serviceLocator.GetAllInstances<ConsumesEvent<DummyEvent>>().Returns(new ConsumesEvent<DummyEvent>[0]);

            subject.Receive(@event);

            serviceLocator.Received().GetAllInstances<ConsumesEvent<DummyEvent>>();
        }
        public void WhenReceivingAnEventThenItWillCheckTheEventStoreToEnsureItsNotAlreadyBeenConsumed()
        {
            var eventStore = Substitute.For<EventStore>();
            var subject = new EventDistributor(null, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);

            eventStore.IsEventAlreadyConsumed(@event).Returns(true);

            subject.Receive(@event);

            eventStore.Received().IsEventAlreadyConsumed(@event);
        }
        public void WhenReceivingAnEventThenItWillCallEachConsumerOfTheEvent()
        {
            var serviceLocator = Substitute.For<IServiceLocator>();
            var eventStore = Substitute.For<EventStore>();
            var subject = new EventDistributor(serviceLocator, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);
            var consumer1 = Substitute.For<ConsumesEvent<DummyEvent>>();
            var consumer2 = Substitute.For<ConsumesEvent<DummyEvent>>();

            serviceLocator.GetAllInstances<ConsumesEvent<DummyEvent>>().Returns(new[] {consumer1, consumer2});

            subject.Receive(@event);

            consumer1.Received().Consume(@event.Event);
            consumer2.Received().Consume(@event.Event);
        }
        public void WhenReceivingAnEventThatIsAlreadyConsumedThenItShouldBeDropped()
        {
            var serviceLocator = Substitute.For<IServiceLocator>();
            var eventStore = Substitute.For<EventStore>();
            var subject = new EventDistributor(serviceLocator, eventStore, new EventTransport[0], null);
            var identity = Guid.NewGuid();
            var @event = new UniqueEvent<DummyEvent>(identity, new DummyEvent(), DateTime.MinValue);

            eventStore.IsEventAlreadyConsumed(@event).Returns(true);

            subject.Receive(@event);

            serviceLocator.DidNotReceiveWithAnyArgs().GetAllInstances(null);
        }