public void PropertiesTest()
        {
            // Arrange.
            const string HeaderName = "TestHeader";
            const string HeaderNamespace = "TestNamespace";
            const string Actor = "TestActor";

            var headerAttributes = new SoapHeaderAttributes();

            // Act.
            Assert.IsFalse(headerAttributes.IsMustUnderstandSet);
            Assert.IsFalse(headerAttributes.IsActorSet);
            Assert.IsFalse(headerAttributes.IsRelaySet);

            headerAttributes.HeaderName = HeaderName;
            headerAttributes.HeaderNamespace = HeaderNamespace;
            headerAttributes.MustUnderstand = true;
            headerAttributes.Actor = Actor;
            headerAttributes.Relay = true;

            // Assert.
            Assert.AreEqual(HeaderName, headerAttributes.HeaderName);
            Assert.AreEqual(HeaderNamespace, headerAttributes.HeaderNamespace);
            
            Assert.IsTrue(headerAttributes.MustUnderstand);
            Assert.IsTrue(headerAttributes.IsMustUnderstandSet);
            
            Assert.AreEqual(Actor, headerAttributes.Actor);
            Assert.IsTrue(headerAttributes.IsActorSet);
            
            Assert.IsTrue(headerAttributes.Relay);
            Assert.IsTrue(headerAttributes.IsRelaySet);
        }
        /// <summary>
        /// Gets the header attributes.
        /// </summary>
        /// <param name="dataContext">
        /// The data context.
        /// </param>
        /// <returns>
        /// The <see cref="SoapHeaderAttributes"/>.
        /// </returns>
        public SoapHeaderAttributes GetHeaderAttributes(IDataContext dataContext)
        {
            var headerAttributes = new SoapHeaderAttributes { HeaderName = Name, HeaderNamespace = XmlNamespace };

            if (MustUnderstandCalculator != null)
                headerAttributes.MustUnderstand = TypeConverter.Convert<bool>(MustUnderstandCalculator.GetValue(dataContext));

            if (ActorCalculator != null)
                headerAttributes.Actor = TypeConverter.Convert<string>(ActorCalculator.GetValue(dataContext));

            if (RelayCalculator != null)
                headerAttributes.Relay = TypeConverter.Convert<bool>(RelayCalculator.GetValue(dataContext));

            return headerAttributes;
        }
        public void SerializationTest()
        {
            // Arrange.
            const string HeaderName = "TestHeader";
            const string HeaderNamespace = "TestNamespace";
            const string Actor = "TestActor";

            // Act.
            var headerAttributes = new SoapHeaderAttributes { HeaderName = HeaderName, HeaderNamespace = HeaderNamespace };
            var element = headerAttributes.GetXElement();
            var deserializedAttributes = SoapHeaderAttributes.CreateHeaderAttributes(element);

            // Assert.
            Assert.AreEqual(HeaderName, deserializedAttributes.HeaderName);
            Assert.AreEqual(HeaderNamespace, deserializedAttributes.HeaderNamespace);
            
            Assert.IsFalse(deserializedAttributes.MustUnderstand);
            Assert.IsFalse(deserializedAttributes.IsMustUnderstandSet);

            Assert.IsTrue(string.IsNullOrEmpty(deserializedAttributes.Actor));
            Assert.IsFalse(deserializedAttributes.IsActorSet);

            Assert.IsFalse(deserializedAttributes.Relay);
            Assert.IsFalse(deserializedAttributes.IsRelaySet);

            // Act.
            headerAttributes = new SoapHeaderAttributes
                                   {
                                       HeaderName = HeaderName,
                                       HeaderNamespace = HeaderNamespace,
                                       MustUnderstand = true,
                                       Actor = Actor,
                                       Relay = true
                                   };
            element = headerAttributes.GetXElement();
            deserializedAttributes = SoapHeaderAttributes.CreateHeaderAttributes(element);

            // Assert.
            Assert.AreEqual(HeaderName, deserializedAttributes.HeaderName);
            Assert.AreEqual(HeaderNamespace, deserializedAttributes.HeaderNamespace);

            Assert.IsTrue(deserializedAttributes.MustUnderstand);
            Assert.IsTrue(deserializedAttributes.IsMustUnderstandSet);

            Assert.AreEqual(Actor, deserializedAttributes.Actor);
            Assert.IsTrue(deserializedAttributes.IsActorSet);

            Assert.IsTrue(deserializedAttributes.Relay);
            Assert.IsTrue(deserializedAttributes.IsRelaySet);

            // Exceptions.
            TestsHelper.VerifyThrow<ArgumentNullException>(() => SoapHeaderAttributes.CreateHeaderAttributes(null));

            var invalidElement1 = new XElement("TestElement");
            TestsHelper.VerifyThrow<InvalidOperationException>(() => SoapHeaderAttributes.CreateHeaderAttributes(invalidElement1));

            var invalidElement2 = new XElement(SoapHeaderAttributes.HeaderElementName);
            TestsHelper.VerifyThrow<InvalidOperationException>(() => SoapHeaderAttributes.CreateHeaderAttributes(invalidElement2));

            var invalidElement3 = new XElement(SoapHeaderAttributes.HeaderElementName);
            invalidElement3.Add(new XAttribute(SoapHeaderAttributes.HeaderNameAttributeName, HeaderName));
            TestsHelper.VerifyThrow<InvalidOperationException>(() => SoapHeaderAttributes.CreateHeaderAttributes(invalidElement3));
        }
        public void ExecuteTest()
        {
            // Arrange.
            const int ServiceDescriptionId = 123;
            const string ServiceName = "TestService";
            const string Username = "******";
            const string ProcessDisplayName = "Test Process";
            const string RequestXml = "Test Request";
            const string ResponseXml = "Test Response";
            var serviceGuid = new Guid("{298F9413-AB7F-4DCC-A3E0-9B5E5640FC68}");

            var headerValueMappingDefinition = new WebMethodParameterMappingDefinition();
            var headerDefinition = new WebMethodHeaderMappingDefinition { ValueMapping = headerValueMappingDefinition };
            var parameterDefinition = new WebMethodParameterMappingDefinition();

            var callDefinition = new WebMethodCallDefinition
                                     {
                                         ServiceDescriptionId = ServiceDescriptionId,
                                         Name = ServiceName,
                                         Guid = serviceGuid,
                                         ProcessDisplayName = ProcessDisplayName
                                     };
            callDefinition.HeaderMappings.Add(headerDefinition);
            callDefinition.ParameterMappings.Add(parameterDefinition);

            var editableRoot = Mock.Create<IEditableRoot>(Behavior.Loose);
            var callContext = Mock.Create<IDataContext>(Behavior.Loose);
            var callContextFactory = Mock.Create<IEditableRootDataContextFactory>(Behavior.Loose);
            Mock.Arrange(() => callContextFactory.CreateDataContext(editableRoot)).Returns(callContext);

            var soapHeaderAttributes = new SoapHeaderAttributes
                                           {
                                               HeaderName = "Test Header",
                                               HeaderNamespace = "Test Namespace",
                                               Actor = "Test Actor",
                                               MustUnderstand = true,
                                               Relay = true
                                           };
            var headerAttributesCalculator = Mock.Create<ISoapHeaderAttributesCalculator>(Behavior.Loose);
            Mock.Arrange(() => headerAttributesCalculator.GetHeaderAttributes(callContext)).Returns(soapHeaderAttributes);

            var headerValue = new object();
            var headerSetter = Mock.Create<IPropertySetter>(Behavior.Loose);
            Mock.Arrange(() => headerSetter.Update(callContext, Arg.IsAny<InputMessage>()))
                .DoInstead<IDataContext, InputMessage>((dc, target) => target.Header = headerValue);

            var parameterValue = new object();
            var parameterSetter = Mock.Create<IPropertySetter>(Behavior.Loose);
            Mock.Arrange(() => parameterSetter.Update(callContext, Arg.IsAny<InputMessage>()))
                .DoInstead<IDataContext, InputMessage>((dc, target) => target.Parameter = parameterValue);

            var mappingFactory = Mock.Create<IWebMethodParameterCalculatorFactory>(Behavior.Loose);
            Mock.Arrange(() => mappingFactory.CreatePropertySetter(typeof(InputMessage), headerValueMappingDefinition)).Returns(headerSetter);
            Mock.Arrange(() => mappingFactory.CreatePropertySetter(typeof(InputMessage), parameterDefinition)).Returns(parameterSetter);

            var headerMappingFactory = Mock.Create<ISoapHeaderAttributesCalculatorFactory>(Behavior.Loose);
            Mock.Arrange(() => headerMappingFactory.CreateCalculator(typeof(InputMessage), headerDefinition)).Returns(headerAttributesCalculator);

            WebMethodCallData callData = null;
            var methodProxy = Mock.Create<IWebMethodProxy>();
            Mock.Arrange(() => methodProxy.RequestType).Returns(typeof(InputMessage));
            Mock.Arrange(() => methodProxy.Invoke(Arg.IsAny<WebMethodCallData>())).DoInstead<WebMethodCallData>(
                data =>
                    {
                        callData = data;
                        if (IntegrationServiceCallScope.Current != null)
                        {
                            IntegrationServiceCallScope.Current.Request = RequestXml;
                            IntegrationServiceCallScope.Current.Response = ResponseXml;
                        }
                    });

            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);

            var serviceCaller = new WebMethodServiceCaller
                                    {
                                        ParameterCalculatorFactory = mappingFactory,
                                        HeaderAttributesCalculatorFactory = headerMappingFactory,
                                        MethodProxy = methodProxy,
                                        EditableRootDataContextFactory = callContextFactory,
                                        Utils = utils,
                                        IntegrationEventLogger = eventLogger
                                    };
            serviceCaller.Initialize(callDefinition);

            // Act.
            serviceCaller.Execute(editableRoot);

            // Assert.
            Assert.IsNotNull(callData);
            var request = callData.Message as InputMessage;

            Assert.IsNotNull(request);
            Assert.AreSame(headerValue, request.Header);
            Assert.AreSame(parameterValue, request.Parameter);
            Assert.AreEqual(1, callData.Options.HeaderAttributes.Count);
            Assert.IsTrue(callData.Options.HeaderAttributes.Contains(soapHeaderAttributes));
            Mock.Assert(() => methodProxy.Invoke(Arg.IsAny<WebMethodCallData>()), Occurs.Once());

            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);
            Assert.AreEqual(RequestXml, events[0].Request);
            Assert.AreEqual(ResponseXml, events[0].Response);

            // Exceptions.
            TestsHelper.VerifyThrow<ArgumentNullException>(() => serviceCaller.Execute(null));
        }
        public void EnqueueServiceCall_InsertsScheduledCall()
        {
            const int ServiceDescriptionId = 123;
            const string ServiceName = "TestService";
            const string SerializedRequest = "TestData";
            const string SerializedOptions = "TestOptions";
            var serviceGuid = new Guid("{298F9413-AB7F-4DCC-A3E0-9B5E5640FC68}");
            const string ProcessName = "TestProcess";
            const int ItemId = 456;

            var headerValueMappingDefinition = new WebMethodParameterMappingDefinition();
            var headerDefinition = new WebMethodHeaderMappingDefinition { ValueMapping = headerValueMappingDefinition };
            var parameterDefinition = new WebMethodParameterMappingDefinition();

            var callDefinition = new WebMethodCallDefinition { ServiceDescriptionId = ServiceDescriptionId, Name = ServiceName, Guid = serviceGuid };
            callDefinition.HeaderMappings.Add(headerDefinition);
            callDefinition.ParameterMappings.Add(parameterDefinition);

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

            var callContext = Mock.Create<IDataContext>(Behavior.Loose);
            var callContextFactory = Mock.Create<IEditableRootDataContextFactory>(Behavior.Loose);
            Mock.Arrange(() => callContextFactory.CreateDataContext(editableRoot)).Returns(callContext);

            var soapHeaderAttributes = new SoapHeaderAttributes
                                           {
                                               HeaderName = "Test Header",
                                               HeaderNamespace = "Test Namespace",
                                               Actor = "Test Actor",
                                               MustUnderstand = true,
                                               Relay = true
                                           };
            var headerAttributesCalculator = Mock.Create<ISoapHeaderAttributesCalculator>(Behavior.Loose);
            Mock.Arrange(() => headerAttributesCalculator.GetHeaderAttributes(callContext)).Returns(soapHeaderAttributes);

            var headerValue = new object();
            var headerSetter = Mock.Create<IPropertySetter>(Behavior.Loose);
            Mock.Arrange(() => headerSetter.Update(callContext, Arg.IsAny<InputMessage>()))
                .DoInstead<IDataContext, InputMessage>((dc, target) => target.Header = headerValue);

            var parameterValue = new object();
            var parameterSetter = Mock.Create<IPropertySetter>(Behavior.Loose);
            Mock.Arrange(() => parameterSetter.Update(callContext, Arg.IsAny<InputMessage>()))
                .DoInstead<IDataContext, InputMessage>((dc, target) => target.Parameter = parameterValue);

            var mappingFactory = Mock.Create<IWebMethodParameterCalculatorFactory>(Behavior.Loose);
            Mock.Arrange(() => mappingFactory.CreatePropertySetter(typeof(InputMessage), headerValueMappingDefinition)).Returns(headerSetter);
            Mock.Arrange(() => mappingFactory.CreatePropertySetter(typeof(InputMessage), parameterDefinition)).Returns(parameterSetter);

            var headerMappingFactory = Mock.Create<ISoapHeaderAttributesCalculatorFactory>(Behavior.Loose);
            Mock.Arrange(() => headerMappingFactory.CreateCalculator(typeof(InputMessage), headerDefinition)).Returns(headerAttributesCalculator);

            var methodProxy = Mock.Create<IWebMethodProxy>(Behavior.Loose);
            Mock.Arrange(() => methodProxy.RequestType).Returns(typeof(InputMessage));
            Mock.Arrange(() => methodProxy.ContractType).Returns(typeof(ITestService));
            Mock.Arrange(() => methodProxy.Method).Returns(typeof(ITestService).GetMethod("TestMethod"));

            var requestSerializer = Mock.Create<IWebMethodRequestSerializer>(Behavior.Loose);
            Mock.Arrange(() => requestSerializer.SerializeRequest(Arg.IsAny<object>())).Returns(SerializedRequest);
            Mock.Arrange(() => requestSerializer.SerializeOptions(Arg.IsAny<WebMethodCallOptions>())).Returns(SerializedOptions);

            WebMethodScheduledCall scheduledCall = null;

            var callScheduler = Mock.Create<IServiceCallScheduler>(Behavior.Loose);
            Mock.Arrange(() => callScheduler.InsertScheduledCall(Arg.IsAny<ServiceScheduledCall>()))
                .DoInstead<ServiceScheduledCall>(sc => scheduledCall = (WebMethodScheduledCall)sc);
            var utils = Mock.Create<IUtils>(Behavior.Loose);
            var eventLogger = Mock.Create<IIntegrationEventLogger>(Behavior.Loose);

            var serviceCaller = new WebMethodServiceCaller
                                    {
                                        ParameterCalculatorFactory = mappingFactory,
                                        HeaderAttributesCalculatorFactory = headerMappingFactory,
                                        MethodProxy = methodProxy,
                                        EditableRootDataContextFactory = callContextFactory,
                                        RequestSerializer = requestSerializer,
                                        CallScheduler = callScheduler,
                                        Utils = utils,
                                        IntegrationEventLogger = eventLogger
                                    };
            serviceCaller.Initialize(callDefinition);

            // Act.
            serviceCaller.EnqueueServiceCall(editableRoot);

            // Assert.
            Mock.Assert(() => callScheduler.InsertScheduledCall(Arg.IsAny<ServiceScheduledCall>()), Occurs.Once());
            Assert.IsNotNull(scheduledCall);
            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(ServiceDescriptionId, scheduledCall.ServiceDescriptionId);
            Assert.AreEqual(typeof(ITestService).AssemblyQualifiedName, scheduledCall.ContractTypeName);
            Assert.AreEqual("TestMethod", scheduledCall.MethodName);
            Assert.AreEqual(SerializedRequest, scheduledCall.Data);
            Assert.AreEqual(SerializedOptions, scheduledCall.Options);
        }
        public void WhenExecutionFails_ServiceCallExceptionIsThrown()
        {
            // Arrange.
            const int ServiceDescriptionId = 123;
            const string ServiceName = "TestService";
            const string SerializedRequest = "TestData";
            const string SerializedOptions = "TestOptions";
            var serviceGuid = new Guid("{298F9413-AB7F-4DCC-A3E0-9B5E5640FC68}");
            const string ProcessName = "TestProcess";
            const int ItemId = 456;

            var headerValueMappingDefinition = new WebMethodParameterMappingDefinition();
            var headerDefinition = new WebMethodHeaderMappingDefinition { ValueMapping = headerValueMappingDefinition };
            var parameterDefinition = new WebMethodParameterMappingDefinition();

            var callDefinition = new WebMethodCallDefinition { ServiceDescriptionId = ServiceDescriptionId, Name = ServiceName, Guid = serviceGuid };
            callDefinition.HeaderMappings.Add(headerDefinition);
            callDefinition.ParameterMappings.Add(parameterDefinition);

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

            var callContext = Mock.Create<IDataContext>(Behavior.Loose);
            var callContextFactory = Mock.Create<IEditableRootDataContextFactory>(Behavior.Loose);
            Mock.Arrange(() => callContextFactory.CreateDataContext(editableRoot)).Returns(callContext);

            var soapHeaderAttributes = new SoapHeaderAttributes
                                           {
                                               HeaderName = "Test Header",
                                               HeaderNamespace = "Test Namespace",
                                               Actor = "Test Actor",
                                               MustUnderstand = true,
                                               Relay = true
                                           };
            var headerAttributesCalculator = Mock.Create<ISoapHeaderAttributesCalculator>(Behavior.Loose);
            Mock.Arrange(() => headerAttributesCalculator.GetHeaderAttributes(callContext)).Returns(soapHeaderAttributes);

            var headerValue = new object();
            var headerSetter = Mock.Create<IPropertySetter>(Behavior.Loose);
            Mock.Arrange(() => headerSetter.Update(callContext, Arg.IsAny<InputMessage>()))
                .DoInstead<IDataContext, InputMessage>((dc, target) => target.Header = headerValue);

            var parameterValue = new object();
            var parameterSetter = Mock.Create<IPropertySetter>(Behavior.Loose);
            Mock.Arrange(() => parameterSetter.Update(callContext, Arg.IsAny<InputMessage>()))
                .DoInstead<IDataContext, InputMessage>((dc, target) => target.Parameter = parameterValue);

            var mappingFactory = Mock.Create<IWebMethodParameterCalculatorFactory>(Behavior.Loose);
            Mock.Arrange(() => mappingFactory.CreatePropertySetter(typeof(InputMessage), headerValueMappingDefinition)).Returns(headerSetter);
            Mock.Arrange(() => mappingFactory.CreatePropertySetter(typeof(InputMessage), parameterDefinition)).Returns(parameterSetter);

            var headerMappingFactory = Mock.Create<ISoapHeaderAttributesCalculatorFactory>(Behavior.Loose);
            Mock.Arrange(() => headerMappingFactory.CreateCalculator(typeof(InputMessage), headerDefinition)).Returns(headerAttributesCalculator);

            var methodProxy = Mock.Create<IWebMethodProxy>(Behavior.Loose);
            Mock.Arrange(() => methodProxy.RequestType).Returns(typeof(InputMessage));
            Mock.Arrange(() => methodProxy.Invoke(Arg.IsAny<WebMethodCallData>())).Throws(new CommunicationException());
            Mock.Arrange(() => methodProxy.ContractType).Returns(typeof(ITestService));
            Mock.Arrange(() => methodProxy.Method).Returns(typeof(ITestService).GetMethod("TestMethod"));

            var requestSerializer = Mock.Create<IWebMethodRequestSerializer>(Behavior.Loose);
            Mock.Arrange(() => requestSerializer.SerializeRequest(Arg.IsAny<object>())).Returns(SerializedRequest);
            Mock.Arrange(() => requestSerializer.SerializeOptions(Arg.IsAny<WebMethodCallOptions>())).Returns(SerializedOptions);

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

            var serviceCaller = new WebMethodServiceCaller
                                    {
                                        ParameterCalculatorFactory = mappingFactory,
                                        HeaderAttributesCalculatorFactory = headerMappingFactory,
                                        MethodProxy = methodProxy,
                                        EditableRootDataContextFactory = callContextFactory,
                                        RequestSerializer = requestSerializer,
                                        CallScheduler = callScheduler,
                                        Utils = utils,
                                        IntegrationEventLogger = eventLogger
                                    };
            serviceCaller.Initialize(callDefinition);

            // Act / Assert.
            TestsHelper.VerifyThrow<ServiceCallException>(() => serviceCaller.Execute(editableRoot));
        }
        /// <summary>
        /// Deserializes an instance of <see cref="SoapHeaderAttributes"/> from a <see cref="XElement"/>.
        /// </summary>
        /// <param name="element">The xml element.</param>
        /// <returns>Returns an instance of <see cref="SoapHeaderAttributes" />.</returns>
        /// <exception cref="System.ArgumentNullException">element</exception>
        /// <exception cref="System.InvalidOperationException">
        /// The element name is invalid.
        /// or
        /// or
        /// </exception>
        /// <exception cref="ArgumentNullException">The <paramref name="element" /> parameter is null.</exception>
        /// <exception cref="InvalidOperationException">The xml element name is not valid.</exception>
        /// <exception cref="InvalidOperationException">The header name attribute is not found in <paramref name="element" />.</exception>
        /// <exception cref="InvalidOperationException">The header namespace attribute in not found in <paramref name="element" />.</exception>
        public static SoapHeaderAttributes CreateHeaderAttributes(XElement element)
        {
            if (element == null)
                throw new ArgumentNullException("element");

            if (element.Name != HeaderElementName)
                throw new InvalidOperationException("The element name is invalid.");

            var attributes = new SoapHeaderAttributes();

            var nameAttribute = element.Attribute(HeaderNameAttributeName);
            if (nameAttribute == null)
                throw new InvalidOperationException(
                    string.Format(CultureInfo.InvariantCulture, "The \"{0}\" attribute was not found.", HeaderNameAttributeName));
            attributes.HeaderName = nameAttribute.Value;

            var namespaceAttribute = element.Attribute(HeaderNamespaceAttributeName);
            if (namespaceAttribute == null)
                throw new InvalidOperationException(
                    string.Format(CultureInfo.InvariantCulture, "The \"{0}\" attribute was not found.", HeaderNamespaceAttributeName));

            attributes.HeaderNamespace = namespaceAttribute.Value;

            var mustUnderstandAttribute = element.Attribute(MustUnderstandAttributeName);
            if (mustUnderstandAttribute != null)
                attributes.MustUnderstand = bool.Parse(mustUnderstandAttribute.Value);

            var actorAttribute = element.Attribute(ActorAttributeName);
            if (actorAttribute != null)
                attributes.Actor = actorAttribute.Value;

            var relayAttribute = element.Attribute(RelayAttributeName);
            if (relayAttribute != null)
                attributes.Relay = bool.Parse(relayAttribute.Value);

            return attributes;
        }
        public void BeforeSendRequestTest()
        {
            // Arrange.
            const string HeaderName1 = "Header1";
            const string HeaderName2 = "Header2";
            const string HeaderNamespace = "TestNamespace";
            const string Actor = "TestActor";

            var oldHeader1 = MessageHeader.CreateHeader(HeaderName1, HeaderNamespace, "Test Value 1");
            var oldHeader2 = MessageHeader.CreateHeader(HeaderName2, HeaderNamespace, "Test Value 2");

            var operationContext = Mock.Create<OperationContext>();
            Mock.Arrange(() => OperationContext.Current).Returns(operationContext);

            var headerAttributes = new SoapHeaderAttributes
                                       {
                                           HeaderName = HeaderName2,
                                           HeaderNamespace = HeaderNamespace,
                                           MustUnderstand = true,
                                           Actor = Actor,
                                           Relay = true
                                       };

            var integrationExtension = new IntegrationServiceOperationContextExtension();
            integrationExtension.HeaderAttributes.Add(headerAttributes);

            var extensions = new ExtensionCollection<OperationContext>(operationContext) { integrationExtension };
            Mock.Arrange(() => operationContext.Extensions).Returns(extensions);

            var message = Mock.Create<Message>();
            var messageHeaders = new MessageHeaders(MessageVersion.Soap11) { oldHeader1, oldHeader2 };
            Mock.Arrange(() => message.Headers).Returns(messageHeaders);

            var inspector = new IntegrationServiceMessageInspector();
            
            // Act.
            var newMessage = message;
            inspector.BeforeSendRequest(ref newMessage, Mock.Create<IClientChannel>());

            // Assert.
            Assert.AreSame(message, newMessage);

            Assert.AreEqual(2, messageHeaders.Count);
            Assert.IsTrue(messageHeaders.Contains(oldHeader1));
            Assert.IsFalse(messageHeaders.Contains(oldHeader2));

            var index = messageHeaders.FindHeader(HeaderName2, HeaderNamespace, Actor);
            var newHeader2 = (XmlElementMessageHeader)messageHeaders[index];

            Assert.IsTrue(newHeader2.MustUnderstand);
            Assert.AreEqual(Actor, newHeader2.Actor);
            Assert.IsTrue(newHeader2.Relay);

            // Exceptions.
            Message nullMessage = null;

            TestsHelper.VerifyThrow<ArgumentNullException>(() => inspector.BeforeSendRequest(ref nullMessage, Mock.Create<IClientChannel>()));

            var message2 = Mock.Create<Message>();
            TestsHelper.VerifyThrow<ArgumentNullException>(() => inspector.BeforeSendRequest(ref message2, null));
        }