Testing 驼峰3:如何使用“interceptSendToEndpoint”拦截来自“OneException”的路由` 问题:
在从Camel 2迁移到Camel 3的过程中,我的错误路由测试失败了 我遵循的模式是强制执行异常,并断言Testing 驼峰3:如何使用“interceptSendToEndpoint”拦截来自“OneException”的路由` 问题:,testing,kotlin,apache-camel,apache-camel-3,Testing,Kotlin,Apache Camel,Apache Camel 3,在从Camel 2迁移到Camel 3的过程中,我的错误路由测试失败了 我遵循的模式是强制执行异常,并断言onException()块使用适当的标记发送到我的度量路由 我正在使用uri模式匹配来单独测试每个标记是否已发出……这会严重影响测试模式 注意:在下面的两个示例中,createRouteBuilder()方法是相同的 传递骆驼2示例 首先,非常感谢您提出了一个框架非常好的问题,并提供了适当的代码示例!Mock component的手册中提到了一个特性的介绍,很可能这就是你所阻止的。我不太
onException()
块使用适当的标记发送到我的度量路由
我正在使用uri模式匹配来单独测试每个标记是否已发出……这会严重影响测试模式
注意:在下面的两个示例中,createRouteBuilder()
方法是相同的
传递骆驼2示例
首先,非常感谢您提出了一个框架非常好的问题,并提供了适当的代码示例!Mock component的手册中提到了一个特性的介绍,很可能这就是你所阻止的。我不太确定哪一个版本的Camel引入了此功能 在任何情况下,为了绕过当前的限制,您可以使用自动模拟功能本身。您的测试方法可以更改如下,以使其正常工作
@Test
fun `exception is routed to error logging route`() {
val exchange = createExchangeWithBody("")
// Create new mock endpoint that will replace our error route
val mockEndpoint = getMockEndpoint("mock:$errorUri")
AdviceWithRouteBuilder.adviceWith(context, startUri) { routeBuilder ->
routeBuilder.mockEndpoints(errorUri)
routeBuilder.interceptSendToEndpoint(errorUri)
.skipSendToOriginalEndpoint()
.to(mockEndpoint)
}
context.start()
mockEndpoint.expectedMessageCount(1)
template.send(startUri, exchange)
assertMockEndpointsSatisfied()
}
对原始代码进行了两次更改
Mock:test
重命名为与自动生成的模拟端点类型一致(Mock:direct:errors
)routeBuilder.mockEndpoints(errorUri)
,以便camel可以自动为模式注入mock,如errorUri
routeBuilder.mockEndpoints(errorUri)
routeBuilder.interceptSendToEndpoint(errorUri)
.skipSendToOriginalEndpoint()
.to(mockEndpoint)
使用一行程序routeBuilder.mockEndpointsAndSkip(errorUri)
,除非您在问题中提到了使用截取的具体原因
其他意见:
运行代码时,如果不做任何更改,将清楚地显示模拟端点中的路由生成器挂钩,mock://test
代替直接:错误
。此外,上下文
似乎也有适当的端点策略
这可能是个bug。虽然有简单的替代方案,但请考虑将此作为一个问题。
有关伟大的@ShellDragon答案的其他信息。在调试您的示例时,我发现了一件有趣的事情。您的示例在camel 3中不起作用,因为SendProcessor丢失了部分代码(doStart方法):
2.x中的目的地“direct:errors”由创建的截取端点重写。
但现在,这段代码被标记为“old cruft”,并被@clausibsen删除。我怀疑这是一个bug,因为简单的拦截SendToEndpoint仍然在工作。使用advicewith+拦截器可能会有变化。这似乎与使用onException()
直接相关。显然,在Camel 3中,您不能再直接从onException
进行拦截,因此将业务逻辑从异常块移到新的路由中允许拦截工作
在我的例子中,这只需要在exchange属性中保存相关的onException
信息,然后在发出度量时可以引用这些信息
import org.apache.camel.RoutesBuilder
import org.apache.camel.builder.AdviceWithRouteBuilder
import org.apache.camel.builder.RouteBuilder
import org.apache.camel.test.junit4.CamelTestSupport
import org.junit.Test
import java.util.concurrent.TimeUnit
class Camel3ErrorInterceptWorking : CamelTestSupport() {
val startUri = "direct:start"
val errorUri = "direct:errors"
val baseMetricsUri = "micrometer:counter:errors"
val fullMetricsUri = "$baseMetricsUri?tags=a=1,b=2"
override fun isUseAdviceWith(): Boolean {
return true
}
override fun createRouteBuilder(): RoutesBuilder {
return object : RouteBuilder() {
override fun configure() {
onException(Exception::class.java)
.to(errorUri)
from(errorUri)
.to(fullMetricsUri) // Moved metrics here from `onException`
from(startUri)
.routeId(startUri)
.throwException(Exception())
}
}
}
@Test
fun `exception is routed to error logging route`() {
val exchange = createExchangeWithBody("")
val mockEndpoint = getMockEndpoint("mock:test")
AdviceWithRouteBuilder.adviceWith(context, startUri) { routeBuilder ->
routeBuilder.interceptSendToEndpoint("$baseMetricsUri.*b.*2.*") // <-- PATTERN
.skipSendToOriginalEndpoint()
.to(mockEndpoint)
}
context.start()
mockEndpoint.expectedMessageCount(1)
template.send(startUri, exchange)
assertMockEndpointsSatisfied(2, TimeUnit.SECONDS)
}
}
import org.apache.camel.RoutesBuilder
导入org.apache.camel.builder.AdviceWithRouteBuilder
导入org.apache.camel.builder.RouteBuilder
导入org.apache.camel.test.junit4.CamelTestSupport
导入org.junit.Test
导入java.util.concurrent.TimeUnit
类Camel3ErrorInterceptWorking:CamelTestSupport(){
val startUri=“直接:开始”
val errorUri=“直接:错误”
val baseMetricsUri=“测微计:计数器:错误”
val fullMetricsUri=“$baseMetricsUri?标记=a=1,b=2”
覆盖乐趣isUseAdviceWith():布尔值{
返回真值
}
重写createRouteBuilder():RouteBuilder{
返回对象:RouteBuilder(){
覆盖乐趣配置(){
OneException(Exception::class.java)
.to(错误URI)
from(errorUri)
.to(fullMetricsUri)//将度量从`OneException'移动到此处`
来自(startUri)
.routeId(startUri)
.ThroweException(异常())
}
}
}
@试验
fun`异常被路由到错误日志记录路由'(){
val exchange=createExchangeWithBody(“”)
val mockEndpoint=getMockEndpoint(“mock:test”)
AdviceWithRouteBuilder.adviceWith(上下文,startUri){routeBuilder->
routeBuilder.interceptSendToEndpoint($baseMetricsUri.*b.*2.*)//谢谢!虽然这在大多数情况下确实很有帮助,但使用mockEndpoints和Skip()
或routeBuilder.mockEndpoints()进行模拟
无法解决我的问题,因为我需要使用正则表达式/模式进行拦截,而这些方法不支持它们。我已更新了我的问题,添加了这些重要的细节
@Test
fun `exception is routed to error logging route`() {
val exchange = createExchangeWithBody("")
// Create new mock endpoint that will replace our error route
val mockEndpoint = getMockEndpoint("mock:$errorUri")
AdviceWithRouteBuilder.adviceWith(context, startUri) { routeBuilder ->
routeBuilder.mockEndpoints(errorUri)
routeBuilder.interceptSendToEndpoint(errorUri)
.skipSendToOriginalEndpoint()
.to(mockEndpoint)
}
context.start()
mockEndpoint.expectedMessageCount(1)
template.send(startUri, exchange)
assertMockEndpointsSatisfied()
}
routeBuilder.mockEndpoints(errorUri)
routeBuilder.interceptSendToEndpoint(errorUri)
.skipSendToOriginalEndpoint()
.to(mockEndpoint)
14:32:34.307 [main] INFO org.apache.camel.reifier.RouteReifier - Adviced route before/after as XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route xmlns="http://camel.apache.org/schema/spring" customId="true" id="direct:start">
<from uri="direct:start"/>
<onException>
<exception>java.lang.Exception</exception>
<to uri="direct:errors"/>
</onException>
<throwException/>
</route>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route xmlns="http://camel.apache.org/schema/spring" customId="true" id="direct:start">
<from uri="direct:start"/>
<onException>
<exception>java.lang.Exception</exception>
<to uri="direct:errors"/>
</onException>
<interceptSendToEndpoint skipSendToOriginalEndpoint="true" uri="direct:errors">
<to uri="mock://test"/>
</interceptSendToEndpoint>
<throwException/>
</route>
import org.apache.camel.Exchange;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Assert;
import org.junit.Test;
public class Camel3RouteTest extends CamelTestSupport {
private static final String startUri = "direct:start";
private static final String errorUri = "direct:errors";
private static final String mockErrorURI = "mock:"+ errorUri;
private static final String ERROR_MESSAGE = "ERROR MESSAGE!";
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
onException(Exception.class)
.to(errorUri);
from(errorUri)
.routeId(errorUri)
.log("error happened!");
from(startUri)
.routeId(startUri)
.throwException(new Exception(ERROR_MESSAGE));
}
};
}
@Test
public void testExecution() throws Exception {
AdviceWithRouteBuilder.adviceWith(context, startUri, adviceWithRouteBuilder -> {
//a.mockEndpointsAndSkip(errorUri);
adviceWithRouteBuilder.mockEndpoints(errorUri);
adviceWithRouteBuilder.interceptSendToEndpoint(errorUri).skipSendToOriginalEndpoint().to(mockErrorURI);
});
MockEndpoint mockEndpoint = getMockEndpoint(mockErrorURI);
mockEndpoint.setExpectedMessageCount(1);
context.start();
sendBody(startUri, "A Test message");
assertMockEndpointsSatisfied();
Assert.assertNotNull(mockEndpoint.getExchanges().get(0).getProperty(Exchange.EXCEPTION_CAUGHT));
Exception receivedException = (Exception) mockEndpoint.getExchanges().get(0).getProperty(Exchange.EXCEPTION_CAUGHT);
Assert.assertTrue(receivedException instanceof Exception);
Assert.assertEquals(receivedException.getMessage(), ERROR_MESSAGE);
}
}
// the destination could since have been intercepted by a interceptSendToEndpoint so we got to
// lookup this before we can use the destination
Endpoint lookup = camelContext.hasEndpoint(destination.getEndpointKey());
if (lookup instanceof InterceptSendToEndpoint) {
if (log.isDebugEnabled()) {
log.debug("Intercepted sending to {} -> {}",
URISupport.sanitizeUri(destination.getEndpointUri()), URISupport.sanitizeUri(lookup.getEndpointUri()));
}
destination = lookup;
}
import org.apache.camel.RoutesBuilder
import org.apache.camel.builder.AdviceWithRouteBuilder
import org.apache.camel.builder.RouteBuilder
import org.apache.camel.test.junit4.CamelTestSupport
import org.junit.Test
import java.util.concurrent.TimeUnit
class Camel3ErrorInterceptWorking : CamelTestSupport() {
val startUri = "direct:start"
val errorUri = "direct:errors"
val baseMetricsUri = "micrometer:counter:errors"
val fullMetricsUri = "$baseMetricsUri?tags=a=1,b=2"
override fun isUseAdviceWith(): Boolean {
return true
}
override fun createRouteBuilder(): RoutesBuilder {
return object : RouteBuilder() {
override fun configure() {
onException(Exception::class.java)
.to(errorUri)
from(errorUri)
.to(fullMetricsUri) // Moved metrics here from `onException`
from(startUri)
.routeId(startUri)
.throwException(Exception())
}
}
}
@Test
fun `exception is routed to error logging route`() {
val exchange = createExchangeWithBody("")
val mockEndpoint = getMockEndpoint("mock:test")
AdviceWithRouteBuilder.adviceWith(context, startUri) { routeBuilder ->
routeBuilder.interceptSendToEndpoint("$baseMetricsUri.*b.*2.*") // <-- PATTERN
.skipSendToOriginalEndpoint()
.to(mockEndpoint)
}
context.start()
mockEndpoint.expectedMessageCount(1)
template.send(startUri, exchange)
assertMockEndpointsSatisfied(2, TimeUnit.SECONDS)
}
}