Testing 驼峰3:如何使用“interceptSendToEndpoint”拦截来自“OneException”的路由` 问题:

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的手册中提到了一个特性的介绍,很可能这就是你所阻止的。我不太

在从Camel 2迁移到Camel 3的过程中,我的错误路由测试失败了

我遵循的模式是强制执行异常,并断言
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)
        }
    }