public async Task GivenPiplelineWithThreeStages_WhenHandlingRequest_ThenAllThreeHandlersHandleRequest()
        {
            var testHandlerA = new TestHandlerA <TestRequestA>();
            var testHandlerB = new TestHandlerB <TestRequestA>();
            var testHandlerC = new TestHandlerC <TestRequestA>();

            Dictionary <Type, Object> dictionary = new Dictionary <Type, object>
            {
                [typeof(TestHandlerA <TestRequestA>)] = testHandlerA,
                [typeof(TestHandlerB <TestRequestA>)] = testHandlerB,
                [typeof(TestHandlerC <TestRequestA>)] = testHandlerC,
            };

            PipelineDefinitionBuilder builder = new PipelineDefinitionBuilder(type => dictionary[type]);

            var pipeline = builder.StartWith <TestHandlerA <TestRequestA>, TestRequestA>()
                           .ThenWith <TestHandlerB <TestRequestA> >()
                           .ThenWith <TestHandlerC <TestRequestA> >()
                           .Build();

            var testRequest = new TestRequestA();
            await pipeline.HandleAsync(testRequest, new Context());

            Assert.Multiple(() =>
            {
                Assert.That(testHandlerA._request, Is.EqualTo(testRequest));
                Assert.That(testHandlerB._request, Is.EqualTo(testRequest));
                Assert.That(testHandlerC._request, Is.EqualTo(testRequest));
            });
        }
        public void AddHandlerTest()
        {
            var handlerA = new TestHandlerA();
            var pipeline = new RuntimePipeline(handlerA);
            var handlerB = new TestHandlerB();
            // B->A
            pipeline.AddHandler(handlerB);

            ValidatePipeline(pipeline, handlerB, handlerA);
        }
        public void AddHandlerTest()
        {
            var handlerA = new TestHandlerA();
            var pipeline = new RuntimePipeline(handlerA);
            var handlerB = new TestHandlerB();

            // B->A
            pipeline.AddHandler(handlerB);

            ValidatePipeline(pipeline, handlerB, handlerA);
        }
        public void AddHandlerBeforeTest()
        {
            var handlerD = new TestHandlerD();
            var pipeline = new RuntimePipeline(handlerD);
            var handlerB = new TestHandlerB();
            // B->D
            pipeline.AddHandler(handlerB);
            var handlerA = new TestHandlerA();
            // A->B->D
            pipeline.AddHandlerBefore<TestHandlerB>(handlerA);
            ValidatePipeline(pipeline, handlerA, handlerB, handlerD);

            var handlerC = new TestHandlerC();
            // A->B->C->D
            pipeline.AddHandlerBefore<TestHandlerD>(handlerC);
            ValidatePipeline(pipeline, handlerA, handlerB, handlerC, handlerD);            
        }
        public void ReplaceHandlerTest()
        {
            var handlerC = new TestHandlerC();
            var pipeline = new RuntimePipeline(handlerC);
            var handlerB = new TestHandlerB();            
            pipeline.AddHandler(handlerB);
            var handlerA = new TestHandlerA();
            //A->B->C
            pipeline.AddHandler(handlerA);
            ValidatePipeline(pipeline, handlerA, handlerB, handlerC);

            var handlerD = new TestHandlerD();
            //A->D->C
            pipeline.ReplaceHandler<TestHandlerB>(handlerD);
            ValidatePipeline(pipeline, handlerA, handlerD, handlerC);
            Assert.IsNull(handlerB.OuterHandler);
            Assert.IsNull(handlerB.InnerHandler);
        }
        public void AddHandlerBeforeTest()
        {
            var handlerD = new TestHandlerD();
            var pipeline = new RuntimePipeline(handlerD);
            var handlerB = new TestHandlerB();

            // B->D
            pipeline.AddHandler(handlerB);
            var handlerA = new TestHandlerA();

            // A->B->D
            pipeline.AddHandlerBefore <TestHandlerB>(handlerA);
            ValidatePipeline(pipeline, handlerA, handlerB, handlerD);

            var handlerC = new TestHandlerC();

            // A->B->C->D
            pipeline.AddHandlerBefore <TestHandlerD>(handlerC);
            ValidatePipeline(pipeline, handlerA, handlerB, handlerC, handlerD);
        }
        public void ReplaceHandlerTest()
        {
            var handlerC = new TestHandlerC();
            var pipeline = new RuntimePipeline(handlerC);
            var handlerB = new TestHandlerB();

            pipeline.AddHandler(handlerB);
            var handlerA = new TestHandlerA();

            //A->B->C
            pipeline.AddHandler(handlerA);
            ValidatePipeline(pipeline, handlerA, handlerB, handlerC);

            var handlerD = new TestHandlerD();

            //A->D->C
            pipeline.ReplaceHandler <TestHandlerB>(handlerD);
            ValidatePipeline(pipeline, handlerA, handlerD, handlerC);
            Assert.IsNull(handlerB.OuterHandler);
            Assert.IsNull(handlerB.InnerHandler);
        }
        public async Task GivenPiplelineWithThreeStages_WhenHandlingRequest_ThenAllThreeHandlersAreCalledInOrder()
        {
            var testHandlerA = new TestHandlerA <TestRequestA>();
            var testHandlerB = new TestHandlerB <TestRequestA>();
            var testHandlerC = new TestHandlerC <TestRequestA>();

            Dictionary <Type, Object> dictionary = new Dictionary <Type, object>
            {
                [typeof(TestHandlerA <TestRequestA>)] = testHandlerA,
                [typeof(TestHandlerB <TestRequestA>)] = testHandlerB,
                [typeof(TestHandlerC <TestRequestA>)] = testHandlerC,
            };

            PipelineDefinitionBuilder builder = new
                                                PipelineDefinitionBuilder(type => dictionary[type]);

            var pipeline = builder.StartWith <TestHandlerA <TestRequestA>, TestRequestA>()
                           .ThenWith <TestHandlerB <TestRequestA> >()
                           .ThenWith <TestHandlerC <TestRequestA> >()
                           .Build();

            var testRequest = new TestRequestA();

            await pipeline.HandleAsync(testRequest, new Context());

            var callOrder = new TestHandler <TestRequestA>[]
            {
                testHandlerA,
                testHandlerB,
                testHandlerC
            }.OrderBy(x => x._timestamp)
            .ToArray();

            Assert.Multiple(() =>
            {
                Assert.That(callOrder[0], Is.EqualTo(testHandlerA));
                Assert.That(callOrder[1], Is.EqualTo(testHandlerB));
                Assert.That(callOrder[2], Is.EqualTo(testHandlerC));
            });
        }
        public async Task GivenPipelineThatChangesRequest_WhenHandlingRequest_ThenChangesRequestInPipeline()
        {
            var testHandlerA        = new TestHandlerA <TestRequestA>();
            var testHandlerB        = new TestHandlerB <TestRequestA>();
            var testMutationHandler = new TestMutationHandler();
            var testHandlerC        = new TestHandlerC <TestRequestB>();

            Dictionary <Type, Object> dictionary = new Dictionary <Type, object>
            {
                [typeof(TestHandlerA <TestRequestA>)] = testHandlerA,
                [typeof(TestHandlerB <TestRequestA>)] = testHandlerB,
                [typeof(TestHandlerC <TestRequestB>)] = testHandlerC,
                [typeof(TestMutationHandler)]         = testMutationHandler,
            };

            PipelineDefinitionBuilder builder = new
                                                PipelineDefinitionBuilder(type => dictionary[type]);


            var pipeline = builder.StartWith <TestHandlerA <TestRequestA>, TestRequestA> ()
                           .ThenWith <TestHandlerB <TestRequestA> >()
                           .ThenWithMutation <TestMutationHandler, TestRequestB>()
                           .ThenWith <TestHandlerC <TestRequestB> >()
                           .Build();

            var testRequest = new TestRequestA();

            await pipeline.HandleAsync(testRequest, new Context());

            Assert.Multiple(() =>
            {
                Assert.That(testHandlerA._request, Is.EqualTo(testRequest));
                Assert.That(testHandlerB._request, Is.EqualTo(testRequest));
                Assert.That(testMutationHandler._request, Is.EqualTo(testRequest));
                Assert.That(testHandlerC._request, Is.Not.EqualTo(testRequest));
                Assert.That(testHandlerC._request, Is.TypeOf <TestRequestB>());
            });
        }