使用 Citrus 框架从 tcp 服务器接收消息并且 Spring 集成超时
Receiving messages from tcp server with Citrus framework and Spring Integration times out
我正在尝试使用 citrus 框架测试一个简单的 tcp send/receive 序列。我能够很好地发送消息,但接收消息证明是有问题的。基本上,citrus 检测不到回复,然后 citrus 超时。
柑橘豆配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:citrus="http://www.citrusframework.org/schema/config"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<citrus:channel-endpoint id="citrusServiceInputEndpoint"
channel-name="input" />
<citrus:channel-endpoint id="citrusServiceRepliesEndpoint"
channel-name="replies" />
<int-ip:tcp-connection-factory id="client"
type="client" host="localhost" port="9123" single-use="false"
so-timeout="10000" using-nio="true" />
<int:channel id="input" />
<int:channel id="replies">
<int:queue capacity="10" />
</int:channel>
<int-ip:tcp-outbound-channel-adapter
id="outboundClient" channel="input" connection-factory="client" />
<int-ip:tcp-inbound-channel-adapter
id="inboundClient" channel="replies" connection-factory="client" />
柑橘类测试用例:
@Test
@CitrusTest(name = "sendSpringIntegrationMessageTest")
public void sendSpringIntegrationMessageTest() throws Exception {
send("citrusServiceInputEndpoint").payload("Req");
receive("citrusServiceRepliesEndpoint").payload("Rsp");
}
我正在使用一个简单的 netcat 服务器进行测试:
nc -kl 9123
当 运行 测试用例时,"Req" 文本在 netcat 上正常到达。但是,当在 netcat 上键入 "Rsp" 时,数据不会到达 citrus 测试。大约 5 秒后,测试用例失败并显示以下消息:
com.consol.citrus.exceptions.TestCaseFailedException: Test case failed
at com.consol.citrus.TestCase.executeAction(TestCase.java:218)
at com.consol.citrus.TestCase.doExecute(TestCase.java:139)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
at com.consol.citrus.Citrus.run(Citrus.java:243)
at com.consol.citrus.dsl.junit.JUnit4CitrusTest.invokeTestMethod(JUnit4CitrusTest.java:90)
at com.consol.citrus.dsl.junit.JUnit4CitrusTestDesigner.invokeTestMethod(JUnit4CitrusTestDesigner.java:68)
at com.consol.citrus.dsl.junit.JUnit4CitrusTest.run(JUnit4CitrusTest.java:71)
at com.consol.citrus.junit.CitrusJUnit4Runner$InvokeRunMethod.evaluate(CitrusJUnit4Runner.java:212)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: com.consol.citrus.exceptions.ActionTimeoutException: Action timeout while receiving message from channel 'replies'
at com.consol.citrus.channel.ChannelConsumer.receive(ChannelConsumer.java:97)
at com.consol.citrus.messaging.AbstractSelectiveMessageConsumer.receive(AbstractSelectiveMessageConsumer.java:50)
at com.consol.citrus.actions.ReceiveMessageAction.receive(ReceiveMessageAction.java:146)
at com.consol.citrus.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:125)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
at com.consol.citrus.TestCase.executeAction(TestCase.java:211)
... 33 more
所以 Citrus 基本上没有收到回复。请注意,我必须为回复通道定义一个队列,因为这是 Citrus 所期望的,回复通道必须实现接口 PollableChannel。
请帮助我理解为什么 Citrus 没有从队列中接收到数据?
默认情况下,tcp 连接工厂希望消息由 \r\n
分隔。
nc
仅用 \n
终止响应,因此连接工厂看不到完整的消息。
参见discussion in the documentation about serializers/deserializers。您需要配置 serializer
和 deserializer
以指向一个 ByteArrayLfSerializer
bean,它只希望 \n
终止消息。
这里是使这个测试工作的正确 bean 配置。按照 Gary 的建议添加了 serializer/deserializer。
我还必须添加一个消息转换器(对象到字符串转换器),因为 Spring 在回复通道上提供的数据将是 byte[] 类型。 Citrus 希望针对字符串类型进行验证,因此需要进行转换才能将字节数组转换为字符串。
希望对以后的人有所帮助!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:citrus="http://www.citrusframework.org/schema/config"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<citrus:channel-endpoint id="citrusServiceInputEndpoint"
channel-name="input" />
<citrus:channel-endpoint id="citrusServiceRepliesEndpoint"
channel-name="response" />
<int-ip:tcp-connection-factory id="client"
type="client" host="localhost" port="9123" single-use="false"
so-timeout="10000" using-nio="true" deserializer="javaSerializer"
serializer="javaSerializer" />
<bean id="javaSerializer"
class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer" />
<int:channel id="input" />
<int:channel id="replies">
</int:channel>
<int:channel id="response">
<int:queue />
</int:channel>
<int:object-to-string-transformer id="transformer" input-channel="replies" output-channel="response" />
<int-ip:tcp-outbound-channel-adapter
id="outboundClient" channel="input" connection-factory="client" />
<int-ip:tcp-inbound-channel-adapter
id="inboundClient" channel="replies" connection-factory="client" />
我正在尝试使用 citrus 框架测试一个简单的 tcp send/receive 序列。我能够很好地发送消息,但接收消息证明是有问题的。基本上,citrus 检测不到回复,然后 citrus 超时。
柑橘豆配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:citrus="http://www.citrusframework.org/schema/config"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<citrus:channel-endpoint id="citrusServiceInputEndpoint"
channel-name="input" />
<citrus:channel-endpoint id="citrusServiceRepliesEndpoint"
channel-name="replies" />
<int-ip:tcp-connection-factory id="client"
type="client" host="localhost" port="9123" single-use="false"
so-timeout="10000" using-nio="true" />
<int:channel id="input" />
<int:channel id="replies">
<int:queue capacity="10" />
</int:channel>
<int-ip:tcp-outbound-channel-adapter
id="outboundClient" channel="input" connection-factory="client" />
<int-ip:tcp-inbound-channel-adapter
id="inboundClient" channel="replies" connection-factory="client" />
柑橘类测试用例:
@Test
@CitrusTest(name = "sendSpringIntegrationMessageTest")
public void sendSpringIntegrationMessageTest() throws Exception {
send("citrusServiceInputEndpoint").payload("Req");
receive("citrusServiceRepliesEndpoint").payload("Rsp");
}
我正在使用一个简单的 netcat 服务器进行测试:
nc -kl 9123
当 运行 测试用例时,"Req" 文本在 netcat 上正常到达。但是,当在 netcat 上键入 "Rsp" 时,数据不会到达 citrus 测试。大约 5 秒后,测试用例失败并显示以下消息:
com.consol.citrus.exceptions.TestCaseFailedException: Test case failed
at com.consol.citrus.TestCase.executeAction(TestCase.java:218)
at com.consol.citrus.TestCase.doExecute(TestCase.java:139)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
at com.consol.citrus.Citrus.run(Citrus.java:243)
at com.consol.citrus.dsl.junit.JUnit4CitrusTest.invokeTestMethod(JUnit4CitrusTest.java:90)
at com.consol.citrus.dsl.junit.JUnit4CitrusTestDesigner.invokeTestMethod(JUnit4CitrusTestDesigner.java:68)
at com.consol.citrus.dsl.junit.JUnit4CitrusTest.run(JUnit4CitrusTest.java:71)
at com.consol.citrus.junit.CitrusJUnit4Runner$InvokeRunMethod.evaluate(CitrusJUnit4Runner.java:212)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: com.consol.citrus.exceptions.ActionTimeoutException: Action timeout while receiving message from channel 'replies'
at com.consol.citrus.channel.ChannelConsumer.receive(ChannelConsumer.java:97)
at com.consol.citrus.messaging.AbstractSelectiveMessageConsumer.receive(AbstractSelectiveMessageConsumer.java:50)
at com.consol.citrus.actions.ReceiveMessageAction.receive(ReceiveMessageAction.java:146)
at com.consol.citrus.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:125)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
at com.consol.citrus.TestCase.executeAction(TestCase.java:211)
... 33 more
所以 Citrus 基本上没有收到回复。请注意,我必须为回复通道定义一个队列,因为这是 Citrus 所期望的,回复通道必须实现接口 PollableChannel。
请帮助我理解为什么 Citrus 没有从队列中接收到数据?
默认情况下,tcp 连接工厂希望消息由 \r\n
分隔。
nc
仅用 \n
终止响应,因此连接工厂看不到完整的消息。
参见discussion in the documentation about serializers/deserializers。您需要配置 serializer
和 deserializer
以指向一个 ByteArrayLfSerializer
bean,它只希望 \n
终止消息。
这里是使这个测试工作的正确 bean 配置。按照 Gary 的建议添加了 serializer/deserializer。
我还必须添加一个消息转换器(对象到字符串转换器),因为 Spring 在回复通道上提供的数据将是 byte[] 类型。 Citrus 希望针对字符串类型进行验证,因此需要进行转换才能将字节数组转换为字符串。
希望对以后的人有所帮助!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:citrus="http://www.citrusframework.org/schema/config"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<citrus:channel-endpoint id="citrusServiceInputEndpoint"
channel-name="input" />
<citrus:channel-endpoint id="citrusServiceRepliesEndpoint"
channel-name="response" />
<int-ip:tcp-connection-factory id="client"
type="client" host="localhost" port="9123" single-use="false"
so-timeout="10000" using-nio="true" deserializer="javaSerializer"
serializer="javaSerializer" />
<bean id="javaSerializer"
class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer" />
<int:channel id="input" />
<int:channel id="replies">
</int:channel>
<int:channel id="response">
<int:queue />
</int:channel>
<int:object-to-string-transformer id="transformer" input-channel="replies" output-channel="response" />
<int-ip:tcp-outbound-channel-adapter
id="outboundClient" channel="input" connection-factory="client" />
<int-ip:tcp-inbound-channel-adapter
id="inboundClient" channel="replies" connection-factory="client" />