使用 Apache Camel 进行单元测试
Unit testing with Apache Camel
我想测试下面的骆驼路线。我在网上找到的所有示例都有以文件开头的路由,在我的例子中,我有一个 spring bean 方法,每隔几分钟调用一次,最后消息被转换并移动到 jms 以及审计目录。
我对这条路线的编写测试一无所知。
我目前在我的测试用例中只有
Mockito.when(tradeService.searchTransaction()).thenReturn(dataWithSingleTransaction);
from("quartz2://tsTimer?cron=0/20+*+8-18+?+*+MON,TUE,WED,THU,FRI+*")
.bean(TradeService.class)
.marshal()
.jacksonxml(true)
.to("jms:queue:out-test")
.to("file:data/test/audit")
.end();
使用 Apache Camel 和 Spring-Boot 进行测试非常简单。
只需执行以下操作(下面的示例是一个抽象示例,只是为了提示您如何操作):
编写测试class
使用Spring-Boot Annotations配置测试class。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@RunWith(SpringRunner.class)
public class MyRouteTest {
@EndpointInject(uri = "{{sourceEndpoint}}")
private ProducerTemplate sourceEndpoint;
....
public void test() {
// send your body to the endpoint. See other provided methods too.
sourceEndpoint.sendBody([your input]);
}
}
在 src/test/application.properties
中:
配置您的 Camel-Endpoints,例如源和目标:
sourceEndpoint=direct:myTestSource
提示:
最好不要在使用 spring-boot 时直接在路由中硬连接起始端点,而是使用 application.properties
。这样就可以更轻松地模拟单元测试的端点,因为您可以在不更改源代码的情况下更改为 direct
-Component。
这意味着代替:
from("quartz2://tsTimer?cron=0/20+*+8-18+?+*+MON,TUE,WED,THU,FRI+*")
你应该写:
from("{{sourceEndpoint}}")
并在 application.properties
中配置 sourceEndpoint
:
sourceEndpoint=quartz2://tsTimer?cron=0/20+*+8-18+?+*+MON,TUE,WED,THU,FRI+*
这样你也可以在不同的情况下使用你的路线。
文档
可以在此处找到有关如何使用 spring-boot 进行测试的很好的文档:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
对于 Apache Camel:http://camel.apache.org/testing.html
@NOD之手 感谢您的提示,我完全走错了方向。阅读您的回答后,我能够编写基本测试,由此我认为我可以将其推进。
感谢您的宝贵时间,但我看到根据我的路线,它应该将 XML 文件放到审核目录中,但实际上并没有发生。
看起来中间步骤也被模拟了,但我没有指定任何内容。
InterceptSendToMockEndpointStrategy - Adviced endpoint [xslt://trans.xslt] with mock endpoint [mock:xslt:trans.xslt]
INFO o.a.c.i.InterceptSendToMockEndpointStrategy - Adviced endpoint [file://test/data/audit/?fileName=%24%7Bheader.outFileName%7D] with mock endpoint [mock:file:test/data/audit/]
INFO o.a.camel.spring.SpringCamelContext - StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
TradePublisherRoute.java
@Override
public void configure() throws Exception {
logger.info("TradePublisherRoute.configure() : trade-publisher started configuring camel route.");
from("{{trade-publisher.sourceEndpoint}}")
.doTry()
.bean(tradeService)
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
String dateStr = Constant.dateFormatForFileName.format(new Date());
logger.info("this is getting executed : " + dateStr);
exchange.setProperty(Constant.KEY_INCOMING_XML_FILE_NAME, "REQ-" + dateStr + Constant.AUDIT_FILE_EXTENSION);
exchange.setProperty(Constant.KEY_OUTGOING_XML_FILE_NAME, "RESP-" + dateStr + Constant.AUDIT_FILE_EXTENSION);
}
})
.marshal()
.jacksonxml(true)
.wireTap("{{trade-publisher.requestAuditDir}}" + "${header.inFileName}")
.to("{{trade-publisher.xsltFile}}")
.to("{{trade-publisher.outboundQueue}}")
.to("{{trade-publisher.responseAuditDir}}" + "${header.outFileName}")
.bean(txnService, "markSuccess")
.endDoTry()
.doCatch(Exception.class)
.bean(txnService, "markFailure")
.log(LoggingLevel.ERROR, "EXCEPTION: ${exception.stacktrace}")
.end();
TradePublisherRouteTest.java
@ActiveProfiles("test")
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = TradePublisherApplication.class)
@MockEndpoints
public class TradePublisherRouteTest {
@EndpointInject(uri = "{{trade-publisher.outboundQueue}}")
private MockEndpoint mockQueue;
@EndpointInject(uri = "{{trade-publisher.sourceEndpoint}}")
private ProducerTemplate producerTemplate;
@MockBean
TradeService tradeService;
private List<Transaction> transactions = new ArrayList<>();
@BeforeClass
public static void beforeClass() {
}
@Before
public void before() throws Exception {
Transaction txn = new Transaction("TEST001", "C001", "100", "JPM", new BigDecimal(100.50), new Date(), new Date(), 1000, "P");
transactions.add(txn);
}
@Test
public void testRouteConfiguration() throws Exception {
Mockito.when(tradeService.searchTransaction()).thenReturn(new Data(transactions));
producerTemplate.sendBody(transactions);
mockQueue.expectedMessageCount(1);
mockQueue.assertIsSatisfied(2000);
}
如有错误请指正!
我想测试下面的骆驼路线。我在网上找到的所有示例都有以文件开头的路由,在我的例子中,我有一个 spring bean 方法,每隔几分钟调用一次,最后消息被转换并移动到 jms 以及审计目录。
我对这条路线的编写测试一无所知。
我目前在我的测试用例中只有
Mockito.when(tradeService.searchTransaction()).thenReturn(dataWithSingleTransaction);
from("quartz2://tsTimer?cron=0/20+*+8-18+?+*+MON,TUE,WED,THU,FRI+*")
.bean(TradeService.class)
.marshal()
.jacksonxml(true)
.to("jms:queue:out-test")
.to("file:data/test/audit")
.end();
使用 Apache Camel 和 Spring-Boot 进行测试非常简单。
只需执行以下操作(下面的示例是一个抽象示例,只是为了提示您如何操作):
编写测试class
使用Spring-Boot Annotations配置测试class。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@RunWith(SpringRunner.class)
public class MyRouteTest {
@EndpointInject(uri = "{{sourceEndpoint}}")
private ProducerTemplate sourceEndpoint;
....
public void test() {
// send your body to the endpoint. See other provided methods too.
sourceEndpoint.sendBody([your input]);
}
}
在 src/test/application.properties
中:
配置您的 Camel-Endpoints,例如源和目标:
sourceEndpoint=direct:myTestSource
提示:
最好不要在使用 spring-boot 时直接在路由中硬连接起始端点,而是使用 application.properties
。这样就可以更轻松地模拟单元测试的端点,因为您可以在不更改源代码的情况下更改为 direct
-Component。
这意味着代替:
from("quartz2://tsTimer?cron=0/20+*+8-18+?+*+MON,TUE,WED,THU,FRI+*")
你应该写:
from("{{sourceEndpoint}}")
并在 application.properties
中配置 sourceEndpoint
:
sourceEndpoint=quartz2://tsTimer?cron=0/20+*+8-18+?+*+MON,TUE,WED,THU,FRI+*
这样你也可以在不同的情况下使用你的路线。
文档
可以在此处找到有关如何使用 spring-boot 进行测试的很好的文档:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
对于 Apache Camel:http://camel.apache.org/testing.html
@NOD之手 感谢您的提示,我完全走错了方向。阅读您的回答后,我能够编写基本测试,由此我认为我可以将其推进。
感谢您的宝贵时间,但我看到根据我的路线,它应该将 XML 文件放到审核目录中,但实际上并没有发生。
看起来中间步骤也被模拟了,但我没有指定任何内容。
InterceptSendToMockEndpointStrategy - Adviced endpoint [xslt://trans.xslt] with mock endpoint [mock:xslt:trans.xslt]
INFO o.a.c.i.InterceptSendToMockEndpointStrategy - Adviced endpoint [file://test/data/audit/?fileName=%24%7Bheader.outFileName%7D] with mock endpoint [mock:file:test/data/audit/]
INFO o.a.camel.spring.SpringCamelContext - StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
TradePublisherRoute.java
@Override
public void configure() throws Exception {
logger.info("TradePublisherRoute.configure() : trade-publisher started configuring camel route.");
from("{{trade-publisher.sourceEndpoint}}")
.doTry()
.bean(tradeService)
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
String dateStr = Constant.dateFormatForFileName.format(new Date());
logger.info("this is getting executed : " + dateStr);
exchange.setProperty(Constant.KEY_INCOMING_XML_FILE_NAME, "REQ-" + dateStr + Constant.AUDIT_FILE_EXTENSION);
exchange.setProperty(Constant.KEY_OUTGOING_XML_FILE_NAME, "RESP-" + dateStr + Constant.AUDIT_FILE_EXTENSION);
}
})
.marshal()
.jacksonxml(true)
.wireTap("{{trade-publisher.requestAuditDir}}" + "${header.inFileName}")
.to("{{trade-publisher.xsltFile}}")
.to("{{trade-publisher.outboundQueue}}")
.to("{{trade-publisher.responseAuditDir}}" + "${header.outFileName}")
.bean(txnService, "markSuccess")
.endDoTry()
.doCatch(Exception.class)
.bean(txnService, "markFailure")
.log(LoggingLevel.ERROR, "EXCEPTION: ${exception.stacktrace}")
.end();
TradePublisherRouteTest.java
@ActiveProfiles("test")
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = TradePublisherApplication.class)
@MockEndpoints
public class TradePublisherRouteTest {
@EndpointInject(uri = "{{trade-publisher.outboundQueue}}")
private MockEndpoint mockQueue;
@EndpointInject(uri = "{{trade-publisher.sourceEndpoint}}")
private ProducerTemplate producerTemplate;
@MockBean
TradeService tradeService;
private List<Transaction> transactions = new ArrayList<>();
@BeforeClass
public static void beforeClass() {
}
@Before
public void before() throws Exception {
Transaction txn = new Transaction("TEST001", "C001", "100", "JPM", new BigDecimal(100.50), new Date(), new Date(), 1000, "P");
transactions.add(txn);
}
@Test
public void testRouteConfiguration() throws Exception {
Mockito.when(tradeService.searchTransaction()).thenReturn(new Data(transactions));
producerTemplate.sendBody(transactions);
mockQueue.expectedMessageCount(1);
mockQueue.assertIsSatisfied(2000);
}
如有错误请指正!