public Response TestMethodComplexMulti(string input, Request request)
        {
            if (_mock != null)
                return _mock.Object.TestMethodComplexMulti(input, request);

            return new Response {ResponseMessage = string.Format("Echo: {0} {1}", input, request.RequestMessage)};
        }
        public Response TestMethodComplex(Request request)
        {
            if (_mock != null)
                return _mock.Object.TestMethodComplex(request);

            return new Response {ResponseMessage = string.Format("Echo: {0}", request.RequestMessage)};
        }
 protected bool Equals(Request other)
 {
     return string.Equals(RequestMessage, other.RequestMessage);
 }
        public void Proxy_RecoversFromFaultedState_WhenCallingMultipleParameterComplexTypeMethod()
        {
            var badRequest = new Request() { RequestMessage = "bad" };
            var goodRequest = new Request() { RequestMessage = "good" };

            var mockService = new Mock<ITestService>();
            mockService.Setup(m => m.TestMethodComplexMulti("good", goodRequest)).Returns(new Response() { ResponseMessage = "OK" });
            mockService.Setup(m => m.TestMethodComplexMulti("bad", badRequest)).Throws<Exception>();

            var serviceHost = InProcTestFactory.CreateHost<ITestService>(new TestServiceImpl(mockService));

            var proxy = WcfClientProxy.Create<ITestService>(c => c.SetEndpoint(serviceHost.Binding, serviceHost.EndpointAddress));

            // Will fault the channel
            Assert.That(() => proxy.TestMethodComplexMulti("bad", badRequest), Throws.Exception);
            Assert.That(() => proxy.TestMethodComplexMulti("good", goodRequest).ResponseMessage, Is.EqualTo("OK"));
        }
        public async Task CallAsync_MethodWithReturnValue2()
        {
            var request = new Request() { RequestMessage = "test" };

            var mockService = new Mock<ITestService>();
            mockService
                .SetupSequence(m => m.TestMethodComplex(It.IsAny<Request>()))
                .Returns(new Response { ResponseMessage = "test", StatusCode = 1 })
                .Returns(new Response { ResponseMessage  = "test", StatusCode = 0 });

            var serviceHost = InProcTestFactory.CreateHost<ITestService>(new TestServiceImpl(mockService));

            var proxy = WcfClientProxy.CreateAsyncProxy<ITestService>(c =>
            {
                c.MaximumRetries(1);
                c.SetEndpoint(serviceHost.Binding, serviceHost.EndpointAddress);
                c.RetryOnResponse<Response>(s => s.StatusCode == 1);
            });

            Console.WriteLine("Caller thread: " + Thread.CurrentThread.ManagedThreadId);

            var result = await proxy.CallAsync(m => m.TestMethodComplex(request));

            Console.WriteLine("Continuation thread: " + Thread.CurrentThread.ManagedThreadId);

            Assert.That(result.StatusCode, Is.EqualTo(0));
            Assert.That(result.ResponseMessage, Is.EqualTo("test"));
        }
        public void Proxy_OnBeforeInvoke_InvokeInfo_SetCorrectly()
        {
            var serviceHost = InProcTestFactory.CreateHost<ITestService>(new TestServiceImpl());

            Request request = new Request() { RequestMessage = "message" };
            var proxy = WcfClientProxy.Create<ITestService>(c =>
            {
                c.SetEndpoint(serviceHost.Binding, serviceHost.EndpointAddress);
                OnInvokeHandler handler = (object sender, OnInvokeHandlerArguments args) =>
                {
                    Assert.AreEqual("TestMethodComplexMulti", args.InvokeInfo.MethodName, "InvokeInfo.MethodName is not set correctly");
                    // parameters
                    Assert.AreEqual(2, args.InvokeInfo.Parameters.Length, "InvokeInfo.Parameters length is incorrect");
                    Assert.AreEqual("test", args.InvokeInfo.Parameters[0], "InvokeInfo.Parameters[0] is not set correctly");
                    Assert.AreEqual(request, args.InvokeInfo.Parameters[1], "InvokeInfo.Parameters[1] is not set correctly");
                };
                c.OnBeforeInvoke += handler;
            });
            proxy.TestMethodComplexMulti("test", request);
        }
        public void Proxy_RecoversFromFaultedState_WhenCallingMultipleParameterComplexTypeMethod()
        {
            var badRequest = new Request() { RequestMessage = "bad" };
            var goodRequest = new Request() { RequestMessage = "good" };

            var service = Substitute.For<ITestService>();
            service.TestMethodComplexMulti("good", goodRequest).Returns(new Response { ResponseMessage = "OK" });
            service.TestMethodComplexMulti("bad", badRequest).Throws<Exception>();

            var proxy = service.StartHostAndProxy();

            // Will fault the channel
            Assert.That(() => proxy.TestMethodComplexMulti("bad", badRequest), Throws.Exception);
            Assert.That(() => proxy.TestMethodComplexMulti("good", goodRequest).ResponseMessage, Is.EqualTo("OK"));
        }
        public void Proxy_OnAfterInvoke_InvokeInfo_SetCorrectly()
        {
            var service = Substitute.For<ITestService>();
            
            Request request = new Request { RequestMessage = "message" };

            var resetEvent = new AutoResetEvent(false);
            var proxy = service.StartHostAndProxy(c =>
            {
                OnInvokeHandler handler = (sender, args) =>
                {
                    Assert.AreEqual("TestMethodComplexMulti", args.InvokeInfo.MethodName, "InvokeInfo.MethodName is not set correctly");
                    // parameters
                    Assert.AreEqual(2, args.InvokeInfo.Parameters.Length, "InvokeInfo.Parameters length is incorrect");
                    Assert.AreEqual("test", args.InvokeInfo.Parameters[0], "InvokeInfo.Parameters[0] is not set correctly");
                    Assert.AreEqual(request, args.InvokeInfo.Parameters[1], "InvokeInfo.Parameters[1] is not set correctly");

                    resetEvent.Set();
                };

                c.OnAfterInvoke += handler;
            });

            proxy.TestMethodComplexMulti("test", request);

            resetEvent.WaitOrFail("OnAfterInvoke not fired");
        }
        public async Task Async_HandleResponse_CanChangeResponse_ForComplexResponse_InterfaceType()
        {
            var service = Substitute.For<ITestService>();

            service
                .TestMethodComplex(Arg.Any<Request>())
                .Returns(m => new Response
                {
                    ResponseMessage = m.Arg<Request>().RequestMessage,
                    StatusCode = 100
                });

            var proxy = service.StartHostAndAsyncProxy(c =>
            {               
                // Rewrite responses with status code of 100
                c.HandleResponse<IResponseStatus>(r =>
                {
                    if (r.StatusCode == 100)
                    {
                        return new Response
                        {
                            ResponseMessage = "error",
                            StatusCode = 1
                        };
                    }
                    
                    return r;
                });
            });

            var request = new Request();
            var response = await proxy.CallAsync(m => m.TestMethodComplex(request));

            Assert.That(response.ResponseMessage, Is.EqualTo("error"));
            Assert.That(response.StatusCode, Is.EqualTo(1));
        }
        public async Task Async_HandleResponse_CanChangeResponse_ForComplexResponseType()
        {
            var service = Substitute.For<ITestService>();

            service
                .TestMethodComplex(Arg.Any<Request>())
                .Returns(m => new Response
                {
                    ResponseMessage = m.Arg<Request>().RequestMessage
                });

            var proxy = service.StartHostAndAsyncProxy(c =>
            {
                c.HandleResponse<Response>(r =>
                {
                    r.ResponseMessage = "hello: " + r.ResponseMessage;
                    return r;
                });
            });

            var request = new Request { RequestMessage = "test" };
            var response = await proxy.CallAsync(m => m.TestMethodComplex(request));

            Assert.That(response.ResponseMessage, Is.EqualTo("hello: test"));
        }    
        public async Task CallAsync_MethodWithReturnValue2()
        {
            var request = new Request() { RequestMessage = "test" };

            var service = Substitute.For<ITestService>();
            service
                .TestMethodComplex(Arg.Any<Request>())
                .Returns(
                    new Response {ResponseMessage = "test", StatusCode = 1},
                    new Response {ResponseMessage = "test", StatusCode = 0});

            var proxy = service.StartHostAndAsyncProxy(c =>
            {
                c.MaximumRetries(1);
                c.RetryOnResponse<Response>(s => s.StatusCode == 1);
            });

            Console.WriteLine("Caller thread: " + Thread.CurrentThread.ManagedThreadId);

            var result = await proxy.CallAsync(m => m.TestMethodComplex(request));

            Console.WriteLine("Continuation thread: " + Thread.CurrentThread.ManagedThreadId);

            Assert.That(result.StatusCode, Is.EqualTo(0));
            Assert.That(result.ResponseMessage, Is.EqualTo("test"));
        }
        public async Task Async_HandleResponse_CanChangeResponse_ForComplexResponse_InterfaceType()
        {
            var mockService = new Mock<ITestService>();

            mockService
                .Setup(m => m.TestMethodComplex(It.IsAny<Request>()))
                .Returns((Request req) => new Response
                {
                    ResponseMessage = req.RequestMessage,
                    StatusCode = 100
                });

            var serviceHost = InProcTestFactory.CreateHost<ITestService>(new TestServiceImpl(mockService));

            var proxy = WcfClientProxy.CreateAsyncProxy<ITestService>(c =>
            {
                c.SetEndpoint(serviceHost.Binding, serviceHost.EndpointAddress);
                
                // Rewrite responses with status code of 100
                c.HandleResponse<IResponseStatus>(r =>
                {
                    if (r.StatusCode == 100)
                    {
                        return new Response
                        {
                            ResponseMessage = "error",
                            StatusCode = 1
                        };
                    }
                    
                    return r;
                });
            });

            var request = new Request();
            var response = await proxy.CallAsync(m => m.TestMethodComplex(request));

            Assert.That(response.ResponseMessage, Is.EqualTo("error"));
            Assert.That(response.StatusCode, Is.EqualTo(1));
        }
        public async Task Async_HandleResponse_CanChangeResponse_ForComplexResponseType()
        {
            var mockService = new Mock<ITestService>();

            mockService
                .Setup(m => m.TestMethodComplex(It.IsAny<Request>()))
                .Returns((Request req) => new Response
                {
                    ResponseMessage = req.RequestMessage
                });

            var serviceHost = InProcTestFactory.CreateHost<ITestService>(new TestServiceImpl(mockService));

            var proxy = WcfClientProxy.CreateAsyncProxy<ITestService>(c =>
            {
                c.SetEndpoint(serviceHost.Binding, serviceHost.EndpointAddress);
                c.HandleResponse<Response>(r =>
                {
                    r.ResponseMessage = "hello: " + r.ResponseMessage;
                    return r;
                });
            });

            var request = new Request { RequestMessage = "test" };
            var response = await proxy.CallAsync(m => m.TestMethodComplex(request));

            Assert.That(response.ResponseMessage, Is.EqualTo("hello: test"));
        }