/// <summary>
        /// Initializes the specified parameter definition.
        /// </summary>
        /// <param name="parameterDefinition">The parameter definition.</param>
        /// <exception cref="System.ArgumentNullException">parameterDefinition</exception>
        public void Initialize(UrlCallParameterDefinition parameterDefinition)
        {
            if (parameterDefinition == null)
                throw new ArgumentNullException("parameterDefinition");

            Name = parameterDefinition.Name;
            _valueExpression = parameterDefinition.ValueExpression;
        }
        public void InitializeTest()
        {
            // Arrange.
            const string ServiceName = "TestService";
            var serviceGuid = new Guid("{E7604DEB-1F4C-4461-ACC2-CFE9CF4FC5D2}");

            var parameterDefinition1 = new UrlCallParameterDefinition();
            var parameterDefinition2 = new UrlCallParameterDefinition();

            var callDefinition = new UrlCallDefinition { Name = ServiceName, Guid = serviceGuid };
            callDefinition.ParameterDefinitions.Add(parameterDefinition1);
            callDefinition.ParameterDefinitions.Add(parameterDefinition2);

            var mappingFactory = new ExportFactory<IUrlCallParameterMapping>(
                () =>
                    {
                        var mapping = new Mock<IUrlCallParameterMapping>();
                        return new Tuple<IUrlCallParameterMapping, Action>(mapping.Object, () => { });
                    });

            var serviceCaller = new UrlServiceCaller { ParameterMappingFactory = mappingFactory };

            // Act.
            try
            {
                serviceCaller.Initialize(null);
                Assert.Fail("ArgumentNullException was expected.");
            }
            catch (ArgumentNullException)
            {
            }

            serviceCaller.Initialize(callDefinition);

            // Assert.
            Assert.AreEqual(ServiceName, serviceCaller.Name);
            Assert.AreEqual(serviceGuid, serviceCaller.Guid);
        }
        public void ExecuteTest()
        {
            // Arrange.
            const string ServiceName = "TestService";
            var serviceGuid = new Guid("{E7604DEB-1F4C-4461-ACC2-CFE9CF4FC5D2}");
            const string Address = "http://example.com/TestService";
            const string Value1 = "value1";
            const string Value2 = "!@#$%^&*()_ {}:=<>";
            const string ProcessDisplayName = "Test Process";
            const string Username = "******";

            var parameterDefinition1 = new UrlCallParameterDefinition();
            var parameterDefinition2 = new UrlCallParameterDefinition();

            var callDefinition = new UrlCallDefinition
                                     {
                                         ProcessDisplayName = ProcessDisplayName,
                                         Name = ServiceName,
                                         Guid = serviceGuid,
                                         CallLocation = UrlServiceCallLocation.Server,
                                         HttpMethod = UrlServiceCallMethod.Post,
                                         AddressExpression = item => Address
                                     };
            callDefinition.ParameterDefinitions.Add(parameterDefinition1);
            callDefinition.ParameterDefinitions.Add(parameterDefinition2);

            var editItem = new Mock<IEditableRoot>();

            var mappingFactory = new ExportFactory<IUrlCallParameterMapping>(
                () =>
                {
                    var mapping = new Mock<IUrlCallParameterMapping>();

                    mapping.Setup(x => x.Initialize(parameterDefinition1)).Callback(
                        () =>
                            {
                                mapping.Setup(x => x.Name).Returns("param1");
                                mapping.Setup(x => x.GetValue(editItem.Object)).Returns(Value1);
                            });

                    mapping.Setup(x => x.Initialize(parameterDefinition2)).Callback(
                        () =>
                            {
                                mapping.Setup(x => x.Name).Returns("param2");
                                mapping.Setup(x => x.GetValue(editItem.Object)).Returns(Value2);
                            });

                    return new Tuple<IUrlCallParameterMapping, Action>(mapping.Object, () => { });
                });

            var utils = Mock.Create<IUtils>(Behavior.Loose);
            Mock.Arrange(() => utils.CurrentUserName).Returns(Username);

            var events = new List<IntegrationEvent>();
            var eventLogger = Mock.Create<IIntegrationEventLogger>(Behavior.Loose);
            Mock.Arrange(() => eventLogger.Log(Arg.IsAny<IntegrationEvent>())).DoInstead<IntegrationEvent>(events.Add);

            UrlServiceCallRequest request = null;

            var requestSender = new Mock<IHttpRequestSender>();
            requestSender.Setup(x => x.SendPostRequest(It.IsAny<UrlServiceCallRequest>())).Callback<UrlServiceCallRequest>(r => { request = r; });

            var serviceCaller = new UrlServiceCaller
                                {
                                    ParameterMappingFactory = mappingFactory,
                                    RequestSender = requestSender.Object,
                                    Utils = utils,
                                    IntegrationEventLogger = eventLogger
                                };
            
            serviceCaller.Initialize(callDefinition);

            // Act.
            TestsHelper.VerifyThrow<ArgumentNullException>(() => serviceCaller.Execute(null));

            serviceCaller.Execute(editItem.Object);

            // Assert.
            requestSender.Verify(x => x.SendPostRequest(It.IsAny<UrlServiceCallRequest>()), Times.Once());
            Assert.IsNotNull(request);
            Assert.AreEqual(Address, request.Url);
            Assert.AreEqual(2, request.ParameterValues.Count);
            
            Assert.AreEqual("param1", request.ParameterValues.ElementAt(0).Name);
            Assert.AreEqual(Value1, request.ParameterValues.ElementAt(0).Value);

            Assert.AreEqual("param2", request.ParameterValues.ElementAt(1).Name);
            Assert.AreEqual(Value2, request.ParameterValues.ElementAt(1).Value);

            Assert.AreEqual(1, events.Count);
            Assert.IsTrue(events[0].IsSuccessful);
            Assert.AreEqual(ProcessDisplayName, events[0].Process);
            Assert.AreEqual(ServiceName, events[0].Service);
            Assert.AreEqual(Username, events[0].Username);
        }
        public void EnqueueServiceCall_InsertsScheduledCall()
        {
            // Arrange.
            const string ServiceName = "TestService";
            var serviceGuid = new Guid("{E7604DEB-1F4C-4461-ACC2-CFE9CF4FC5D2}");
            const string Address = "http://example.com/TestService";
            const string Value1 = "value1";
            const string Value2 = "!@#$%^&*()_ {}:=<>";
            const string ExpectedContent = "param1=value1&param2=!%40%23%24%25%5e%26*()_+%7b%7d%3a%3d%3c%3e";
            const string ProcessName = "TestProcess";
            const int ItemId = 123;

            var parameterDefinition1 = new UrlCallParameterDefinition();
            var parameterDefinition2 = new UrlCallParameterDefinition();

            var callDefinition = new UrlCallDefinition
                                 {
                                     Name = ServiceName,
                                     Guid = serviceGuid,
                                     CallLocation = UrlServiceCallLocation.Server,
                                     HttpMethod = UrlServiceCallMethod.Post,
                                     AddressExpression = item => Address
                                 };
            callDefinition.ParameterDefinitions.Add(parameterDefinition1);
            callDefinition.ParameterDefinitions.Add(parameterDefinition2);

            var editItem = Mock.Create<IEditableRoot>(Behavior.Loose);
            Mock.Arrange(() => editItem.ProcessName).Returns(ProcessName);
            Mock.Arrange(() => editItem.Id).Returns(ItemId);

            var mappingFactory = new ExportFactory<IUrlCallParameterMapping>(
                () =>
                {
                    var mapping = new Mock<IUrlCallParameterMapping>();

                    mapping.Setup(x => x.Initialize(parameterDefinition1)).Callback(
                        () =>
                        {
                            mapping.Setup(x => x.Name).Returns("param1");
                            mapping.Setup(x => x.GetValue(editItem)).Returns(Value1);
                        });

                    mapping.Setup(x => x.Initialize(parameterDefinition2)).Callback(
                        () =>
                        {
                            mapping.Setup(x => x.Name).Returns("param2");
                            mapping.Setup(x => x.GetValue(editItem)).Returns(Value2);
                        });

                    return new Tuple<IUrlCallParameterMapping, Action>(mapping.Object, () => { });
                });

            var scheduledCalls = new List<ServiceScheduledCall>();
            var callScheduler = Mock.Create<IServiceCallScheduler>(Behavior.Loose);
            Mock.Arrange(() => callScheduler.InsertScheduledCall(Arg.IsAny<ServiceScheduledCall>()))
                .DoInstead<ServiceScheduledCall>(scheduledCalls.Add);
            var utils = Mock.Create<IUtils>(Behavior.Loose);
            var eventLogger = Mock.Create<IIntegrationEventLogger>(Behavior.Loose);

            var serviceCaller = new UrlServiceCaller
                                {
                                    ParameterMappingFactory = mappingFactory,
                                    CallScheduler = callScheduler,
                                    Utils = utils,
                                    IntegrationEventLogger = eventLogger
                                };
            serviceCaller.Initialize(callDefinition);

            // Act.
            serviceCaller.EnqueueServiceCall(editItem);

            // Assert.
            Assert.AreEqual(1, scheduledCalls.Count);
            var scheduledCall = (UrlScheduledCall)scheduledCalls[0];
            Assert.AreEqual(serviceGuid, scheduledCall.IntegrationServiceGuid);
            Assert.AreEqual(ProcessName, scheduledCall.ProcessName);
            Assert.AreEqual(ItemId, scheduledCall.ItemId);
            Assert.AreEqual(0, scheduledCall.CallCount);
            Assert.AreEqual(ServiceCallStatus.Scheduled, scheduledCall.Status);
            Assert.AreEqual(Address, scheduledCall.Url);
            Assert.AreEqual(ExpectedContent, scheduledCall.Data);
            Assert.AreEqual(UrlServiceCallMethod.Post, scheduledCall.HttpMethod);
        }
        public void GetRequestTest()
        {
            // Arrange.
            const string ServiceName = "TestService";
            var serviceGuid = new Guid("{E7604DEB-1F4C-4461-ACC2-CFE9CF4FC5D2}");
            const string Address = "http://example.com/TestService";
            const string Value1 = "value1";
            const string Value2 = "!@#$%^&*()_ {}:=<>";

            var parameterDefinition1 = new UrlCallParameterDefinition();
            var parameterDefinition2 = new UrlCallParameterDefinition();

            var callDefinition = new UrlCallDefinition
                                     {
                                         Name = ServiceName,
                                         Guid = serviceGuid,
                                         CallLocation = UrlServiceCallLocation.Server,
                                         HttpMethod = UrlServiceCallMethod.Post,
                                         AddressExpression = item => Address
                                     };
            callDefinition.ParameterDefinitions.Add(parameterDefinition1);
            callDefinition.ParameterDefinitions.Add(parameterDefinition2);

            var editItem = new Mock<IEditableRoot>();

            var mappingFactory = new ExportFactory<IUrlCallParameterMapping>(
                () =>
                    {
                        var mapping = new Mock<IUrlCallParameterMapping>();

                        mapping.Setup(x => x.Initialize(parameterDefinition1)).Callback(
                            () =>
                                {
                                    mapping.Setup(x => x.Name).Returns("param1");
                                    mapping.Setup(x => x.GetValue(editItem.Object)).Returns(Value1);
                                });

                        mapping.Setup(x => x.Initialize(parameterDefinition2)).Callback(
                            () =>
                                {
                                    mapping.Setup(x => x.Name).Returns("param2");
                                    mapping.Setup(x => x.GetValue(editItem.Object)).Returns(Value2);
                                });

                        return new Tuple<IUrlCallParameterMapping, Action>(mapping.Object, () => { });
                    });

            var serviceCaller = new UrlServiceCaller { ParameterMappingFactory = mappingFactory };
            serviceCaller.Initialize(callDefinition);

            // Act.
            TestsHelper.VerifyThrow<ArgumentNullException>(() => serviceCaller.GetRequest(null));

            var request = serviceCaller.GetRequest(editItem.Object);

            // Assert.
            Assert.IsNotNull(request);
            Assert.AreEqual(Address, request.Url);
            Assert.AreEqual(2, request.ParameterValues.Count);

            Assert.AreEqual("param1", request.ParameterValues.ElementAt(0).Name);
            Assert.AreEqual(Value1, request.ParameterValues.ElementAt(0).Value);

            Assert.AreEqual("param2", request.ParameterValues.ElementAt(1).Name);
            Assert.AreEqual(Value2, request.ParameterValues.ElementAt(1).Value);
        }
        public void WhenExecutionFails_ServiceCallExceptionIsThrown()
        {
            // Arrange.
            const string ServiceName = "TestService";
            var serviceGuid = new Guid("{E7604DEB-1F4C-4461-ACC2-CFE9CF4FC5D2}");
            const string Address = "http://example.com/TestService";
            const string Value1 = "value1";
            const string Value2 = "!@#$%^&*()_ {}:=<>";
            const string ExpectedContent = @"param1=value1&param2=!%40%23%24%25%5e%26*()_+%7b%7d%3a%3d%3c%3e";
            const string ProcessName = "TestProcess";
            const int ItemId = 123;

            var parameterDefinition1 = new UrlCallParameterDefinition();
            var parameterDefinition2 = new UrlCallParameterDefinition();

            var callDefinition = new UrlCallDefinition
                                     {
                                         Name = ServiceName,
                                         Guid = serviceGuid,
                                         CallLocation = UrlServiceCallLocation.Server,
                                         HttpMethod = UrlServiceCallMethod.Post,
                                         AddressExpression = item => Address
                                     };
            callDefinition.ParameterDefinitions.Add(parameterDefinition1);
            callDefinition.ParameterDefinitions.Add(parameterDefinition2);

            var editItem = new Mock<IEditableRoot>();
            editItem.Setup(x => x.Id).Returns(ItemId);
            editItem.Setup(x => x.ProcessName).Returns(ProcessName);

            var mappingFactory = new ExportFactory<IUrlCallParameterMapping>(
                () =>
                {
                    var mapping = new Mock<IUrlCallParameterMapping>();

                    mapping.Setup(x => x.Initialize(parameterDefinition1)).Callback(
                        () =>
                        {
                            mapping.Setup(x => x.Name).Returns("param1");
                            mapping.Setup(x => x.GetValue(editItem.Object)).Returns(Value1);
                        });

                    mapping.Setup(x => x.Initialize(parameterDefinition2)).Callback(
                        () =>
                        {
                            mapping.Setup(x => x.Name).Returns("param2");
                            mapping.Setup(x => x.GetValue(editItem.Object)).Returns(Value2);
                        });

                    return new Tuple<IUrlCallParameterMapping, Action>(mapping.Object, () => { });
                });

            var requestSender = new Mock<IHttpRequestSender>();
            requestSender.Setup(x => x.SendPostRequest(It.IsAny<UrlServiceCallRequest>())).Throws(new TestException());

            var callScheduler = new Mock<IServiceCallScheduler>();
            var utils = Mock.Create<IUtils>(Behavior.Loose);
            var eventLogger = Mock.Create<IIntegrationEventLogger>(Behavior.Loose);

            var serviceCaller = new UrlServiceCaller
                                {
                                    ParameterMappingFactory = mappingFactory,
                                    RequestSender = requestSender.Object,
                                    CallScheduler = callScheduler.Object,
                                    Utils = utils,
                                    IntegrationEventLogger = eventLogger
                                };
            serviceCaller.Initialize(callDefinition);

            // Act / Assert.
            TestsHelper.VerifyThrow<ServiceCallException>(() => serviceCaller.Execute(editItem.Object));
        }