使用 Citrus Automation Framework 为多个响应创建模拟服务的最佳实践是什么?

What is the best practice to create a mock service with Citrus Automation Framework for multiple responses?

我已经使用 Citrus Framework 安装了组件集成测试套件。为了为不同的组件创建模拟服务。我一直在 XPathPayloadMappingKeyExtractor 的帮助下使用简单的映射策略。

我面临的挑战是为不同的 soap 请求创建多个响应。

我一直在努力理解它的响应方式。任何有经验的人可以帮助我解决柑橘和 Spring 问题?

我的上下文文件:

<citrus-ws:client id="ClientEndpoint"
                  request-url="http://localhost:8085/"/>




<citrus-ws:server id="BS_Customer_Information"
                  port="8085"
                  auto-start="true"/>

我的测试方法:

 @CitrusTest
public void testingServer() {

    soap().client(ClientEndpoint)
            .send()
            .soapAction("urn:RetrieveAddressBookOP_01")
            .payload(new ClassPathResource("Requests/Sample1.xml"));



    soap().server(BS_Customer_Information)
            .receive()
            .soapAction("urn:RetrieveAddressBookOP_01");

    soap().server(BS_Customer_Information)
            .send()
            .payload(new ClassPathResource("AtomicResponses/Response1.xml"));


    soap().client(ClientEndpoint)
            .receive()
            .messageType(MessageType.XML);

}

问题 1:我的 Soap 客户端超时,无法获得响应

问题 1:是否应将服务器响应解析为 Soap Env 和 Body?

问题 2:为什么我已经定义了我的响应,它仍然调用转到频道 Endpoint.inbound?

控制台日志:

2521   DEBUG gEndpointInterceptor| Received SOAP request:
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<RetrieveAddressBookOP_01"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

2527   DEBUG r.WebServiceEndpoint| Received SOAP request:
SOAPMESSAGE [payload: <?xml version="1.0" encoding="UTF-8"?><au:RetrieveAddressBookOP_01 xmlns:au="au.com.teysau.dataservice"/>][headers: {citrus_message_id=e1311140-6ee3-415a-815e-0d162cbc03c1, citrus_message_timestamp=1490649843807, citrus_soap_action=urn:RetrieveAddressBookOP_01, citrus_http_request_uri=/, citrus_http_context_path=, citrus_http_query_params=, citrus_http_method=POST}][header-data: [<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>]][attachments: []]
2527   DEBUG annelEndpointAdapter| Forwarding request to message channel ...
2527   DEBUG t.TestContextFactory| Created new test context - using global variables: '{}'
2527   DEBUG ltCorrelationManager| Saving correlation key for 'citrus_message_correlator_ChannelEndpointAdapter:producer'
2527   DEBUG  context.TestContext| Setting variable: citrus_message_correlator_ChannelEndpointAdapter:producer with value: 'citrus_message_id = 'e1311140-6ee3-415a-815e-0d162cbc03c1''
2527   DEBUG .ChannelSyncProducer| Sending message to channel: 'BS_Customer_Information.inbound'
2527   DEBUG .ChannelSyncProducer| Message to send is:
SOAPMESSAGE [payload: <?xml version="1.0" encoding="UTF-8"?><RetrieveAddressBookOP_01"/>][headers: {citrus_message_id=e1311140-6ee3-415a-815e-0d162cbc03c1, citrus_message_timestamp=1490649843807, citrus_soap_action=urn:RetrieveAddressBookOP_01, citrus_http_request_uri=/, citrus_http_context_path=, citrus_http_query_params=, citrus_http_method=POST}][header-data: [<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>]][attachments: []]
2527   INFO  .ChannelSyncProducer| Message was sent to channel: 'BS_Customer_Information.inbound'
3539   WARN  annelEndpointAdapter| Reply timed out after 1000ms. Did not receive reply message on reply channel
3540   DEBUG annelEndpointAdapter| Did not receive reply message - no response is simulated
3540   DEBUG r.WebServiceEndpoint| No reply message from endpoint adapter 'com.consol.citrus.channel.ChannelEndpointAdapter@6dbd0a41'
3540   WARN  r.WebServiceEndpoint| No SOAP response for calling client
3542   DEBUG ageDispatcherServlet| Successfully completed request
3546   DEBUG        server.Server| RESPONSE /  202 handled=true
3546   DEBUG ver.HttpChannelState| HttpChannelState@244a4722{s=DISPATCHED i=true a=null} unhandle DISPATCHED
3553   DEBUG erver.HttpConnection| org.eclipse.jetty.server.HttpConnection$SendCallback@27d2cb2e[PROCESSING][i=ResponseInfo{HTTP/1.1 202 null,-1,false},cb=org.eclipse.jetty.server.HttpChannel$CommitCallback@2f1ea019] generate: NEED_HEADER (null,[p=0,l=0,c=0,r=0],true)@START
3556   DEBUG erver.HttpConnection| org.eclipse.jetty.server.HttpConnection$SendCallback@27d2cb2e[PROCESSING][i=ResponseInfo{HTTP/1.1 202 null,-1,false},cb=org.eclipse.jetty.server.HttpChannel$CommitCallback@2f1ea019] generate: FLUSH ([p=0,l=114,c=8192,r=114],[p=0,l=0,c=0,r=0],true)@COMPLETING
3556   DEBUG      io.WriteFlusher| write: WriteFlusher@76f08437{IDLE} [HeapByteBuffer@2c34f7c0[p=0,l=114,c=8192,r=114]={<<<HTTP/1.1 202 Acce....v20160210)\r\n\r\n>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}]
3557   DEBUG      io.WriteFlusher| update WriteFlusher@76f08437{WRITING}:IDLE-->WRITING
3562   INFO  ent.WebServiceClient| SOAP message was sent to endpoint: 'http://localhost:8085/'
3562   INFO  ent.WebServiceClient| Received no SOAP response from endpoint: 'http://localhost:8085/'
3562   INFO         citrus.Citrus| 
3562   DEBUG        citrus.Citrus| TEST STEP 1/4 SUCCESS
3562   INFO         citrus.Citrus| 
3562   DEBUG        citrus.Citrus| TEST STEP 2/4: receive
3563   DEBUG   io.ChannelEndPoint| flushed 114 SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,-,W,1092/30000,HttpConnection}{io=0,kio=0,kro=1}
3566   DEBUG nnel.ChannelConsumer| Receiving message from: BS_Customer_Information.inbound
3567   DEBUG nnel.ChannelConsumer| Received message from: BS_Customer_Information.inbound
3567   DEBUG ltCorrelationManager| Saving correlation key for 'citrus_message_correlator_BS_Customer_Information:consumer'
3567   DEBUG  context.TestContext| Setting variable: citrus_message_correlator_BS_Customer_Information:consumer with value: 'citrus_message_id = 'e1311140-6ee3-415a-815e-0d162cbc03c1''
3567   DEBUG ltCorrelationManager| Saving correlated object for 'citrus_message_id = 'e1311140-6ee3-415a-815e-0d162cbc03c1''
3567   DEBUG ageValidatorRegistry| Found 3 message validators for message type: XML
3567   DEBUG mXmlMessageValidator| Start message validation ...
3567   DEBUG mXmlMessageValidator| Start XML message validation
3569   DEBUG mXmlMessageValidator| Starting XML schema validation ...
3569   WARN  mXmlMessageValidator| Neither schema instance nor schema repository defined - skipping XML schema validation
3569   INFO  mXmlMessageValidator| XML message validation successful: All values OK
3569   DEBUG mXmlMessageValidator| Start message header validation ...
3570   DEBUG      io.WriteFlusher| update WriteFlusher@76f08437{IDLE}:WRITING-->IDLE
3570   DEBUG erver.HttpConnection| org.eclipse.jetty.server.HttpConnection$SendCallback@27d2cb2e[PROCESSING][i=ResponseInfo{HTTP/1.1 202 null,-1,false},cb=org.eclipse.jetty.server.HttpChannel$CommitCallback@2f1ea019] generate: DONE ([p=114,l=114,c=8192,r=0],[p=0,l=0,c=0,r=0],true)@END
3570   DEBUG mXmlMessageValidator| Validating header element: citrus_soap_action='urn:RetrieveAddressBookOP_01': OK.
3571   INFO  mXmlMessageValidator| Message header validation successful: All properties OK
3571   INFO  mXmlMessageValidator| Message validation successful: All values OK
3571   INFO         citrus.Citrus| 
3571   DEBUG        citrus.Citrus| TEST STEP 2/4 SUCCESS
3571   INFO         citrus.Citrus| 
3571   DEBUG        citrus.Citrus| TEST STEP 3/4: send
3571   DEBUG ngCorrelationManager| Get correlation key for 'citrus_message_correlator_BS_Customer_Information:consumer'
3571   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = 'e1311140-6ee3-415a-815e-0d162cbc03c1''
3571   DEBUG .ChannelSyncConsumer| Sending message to reply channel: 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66f66866'
3571   DEBUG .ChannelSyncConsumer| Message to send is:
SOAPMESSAGE [payload: <AddressBook>
            <Address>
                <Address_Number>14</Address_Number>
                <Long_Address>Willis Street</Long_Address>
                <Tax_ID>7987398</Tax_ID>
                <Alpha_Name>what is alpha</Alpha_Name>
                <Code>UN_</Code>
                <Mailing_Name>James Bond</Mailing_Name>
                <Address_Line1>take the first part of the long address</Address_Line1>
                <Address_Line2>You may take the second part not</Address_Line2>
                <Postal_Code>8900</Postal_Code>
                <City>WLN</City>
                <Country>NZ</Country>
                <Prefix>233</Prefix>
                <Phone_Number>025364</Phone_Number>
                <Prefix_2 xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
                <Phone_Number2 xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
                <userID>s3b9d</userID>
                <BatchNumber>jkdhj59</BatchNumber>
                <Tansaction_Number>jkd3j29</Tansaction_Number>
                <Line_Number>291597</Line_Number>
            </Address>
        </AddressBook>][headers: {citrus_message_id=fd946a46-f67a-405d-b118-b1b6b3d562c1, citrus_message_timestamp=1490649843443}][attachments: []]
3572   WARN  emporaryReplyChannel| Reply message received but the receiving thread has exited due to a timeout:GenericMessage [payload=SOAPMESSAGE [payload: <AddressBook>
            <Address>
                <Address_Number>14</Address_Number>
                <Long_Address>Willis Street</Long_Address>
                <Tax_ID>7987398</Tax_ID>
                <Alpha_Name>what is alpha</Alpha_Name>
                <Code>UN_</Code>
                <Mailing_Name>James Bond</Mailing_Name>
                <Address_Line1>take the first part of the long address</Address_Line1>
                <Address_Line2>You may take the second part not</Address_Line2>
                <Postal_Code>8900</Postal_Code>
                <City>WLN</City>
                <Country>NZ</Country>
                <Prefix>233</Prefix>
                <Phone_Number>025364</Phone_Number>
                <Prefix_2 xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
                <Phone_Number2 xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
                <userID>s3b9d</userID>
                <BatchNumber>jkdhj59</BatchNumber>
                <Tansaction_Number>jkd3j29</Tansaction_Number>
                <Line_Number>291597</Line_Number>
            </Address>
        </AddressBook>][headers: {citrus_message_id=fd946a46-f67a-405d-b118-b1b6b3d562c1, citrus_message_timestamp=1490649843443}][attachments: []], headers={id=cfc4eeaa-eac8-8f00-2f45-2e3fcb16fdb6, timestamp=1490649844854}]
3572   INFO  .ChannelSyncConsumer| Message was sent to reply channel: 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66f66866'
3572   INFO         citrus.Citrus| 
3572   DEBUG        citrus.Citrus| TEST STEP 3/4 SUCCESS
3572   INFO         citrus.Citrus| 
3572   DEBUG        citrus.Citrus| TEST STEP 4/4: receive
3572   DEBUG ngCorrelationManager| Get correlation key for 'citrus_message_correlator_ClientEndpoint'
3572   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
3572   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
3575   DEBUG      http.HttpParser| reset HttpParser{s=END,214 of 214}
3576   DEBUG      http.HttpParser| END --> START
3576   DEBUG   server.HttpChannel| HttpChannelOverHttp@4820529f{r=1,c=false,a=IDLE,uri=} handle exit, result COMPLETE
3576   DEBUG   io.ChannelEndPoint| filled 0 SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,-,-,13/30000,HttpConnection}{io=0,kio=0,kro=1}
3576   DEBUG   io.ChannelEndPoint| filled 0 SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,-,-,13/30000,HttpConnection}{io=0,kio=0,kro=1}
3576   DEBUG      http.HttpParser| parseNext s=START HeapByteBuffer@6b681750[p=0,l=0,c=16384,r=0]={<<<>>>POST / HTTP/1.1\r\n...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
3576   DEBUG o.AbstractConnection| fillInterested HttpConnection@2c01adea[FILLING,SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,-,-,13/30000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of -1},g=HttpGenerator{s=START},c=HttpChannelOverHttp@4820529f{r=1,c=false,a=IDLE,uri=}]
3576   DEBUG o.AbstractConnection| FILLING-->FILLING_FILL_INTERESTED HttpConnection@2c01adea[FILLING_FILL_INTERESTED,SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,-,-,13/30000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of -1},g=HttpGenerator{s=START},c=HttpChannelOverHttp@4820529f{r=1,c=false,a=IDLE,uri=}]
3577   DEBUG o.AbstractConnection| FILLING_FILL_INTERESTED-->FILL_INTERESTED HttpConnection@2c01adea[FILL_INTERESTED,SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,-,-,13/30000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of -1},g=HttpGenerator{s=START},c=HttpChannelOverHttp@4820529f{r=1,c=false,a=IDLE,uri=}]
3577   DEBUG electChannelEndPoint| Local interests updating 0 -> 1 for SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,R,-,0/30000,HttpConnection}{io=1,kio=0,kro=1}
3577   DEBUG   io.SelectorManager| Queued change org.eclipse.jetty.io.SelectChannelEndPoint@67e66c5c
3578   DEBUG   io.SelectorManager| Selector loop woken up from select, 0/1 selected
3578   DEBUG   io.SelectorManager| Running change org.eclipse.jetty.io.SelectChannelEndPoint@67e66c5c
3578   DEBUG electChannelEndPoint| Key interests updated 0 -> 1 on SelectChannelEndPoint@1c2a40b4{/127.0.0.1:54924<->8085,Open,in,out,R,-,1/30000,HttpConnection}{io=1,kio=1,kro=1}
3578   DEBUG   io.SelectorManager| Selector loop waiting on select
4072   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
4072   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
4573   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
4573   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
5073   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
5073   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
5574   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
5574   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
6075   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
6075   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
6575   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
6575   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
7075   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
7075   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
7576   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
7576   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
8076   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
8076   DEBUG   citrus.RetryLogger| Reply message did not arrive yet - retrying in 500ms
8576   DEBUG ltCorrelationManager| Finding correlated object for 'citrus_message_id = '69b4056a-cae6-4004-a837-41de069865b8''
8580   INFO   report.JIRAConsumer| Invoking JIRA API...
works.integration.jira.exceptions.ServiceBindingException: Missing Required Properties - SUMMARY, EXMESSAGE, DETAILEDEXCEPTION, PROJECT

您必须向第一个 `soap().client().send()' 操作添加 fork(true) 选项,因为 Http SOAP 协议本质上是同步的。测试中的第一个操作等待同步响应并阻止其余测试用例的执行。

显然,您的测试需要在客户端响应 soap().server() 之前接收一些其他消息。这就是为什么您需要首先分叉客户端发送操作,以便服务器操作可以在客户端响应到达之前执行。

一般来说,Citrus 中的 SOAP 组件会自动处理 SOAP 信封和 SOAP 主体。所以你只需要将纯正文内容定义为有效载荷。自动添加 SOAP 信封。

希望现在更清楚了。