【问题标题】:Camel mock endpoint for pollEnrichpollEnrich 的骆驼模拟端点
【发布时间】:2023-11-05 08:11:01
【问题描述】:

我尝试模拟 pollEnrich 的端点,但没有成功。使用adviceWith 模拟对.to("").enrich("") 来说效果很好,但是对于pollEnrich 我遇到了错误:
org.apache.http.conn.HttpHostConnectException: Connect to localhost:8983
我不明白为什么adviceWith 不适合pollEnrich 这是模拟代码:

public class PollEnricherRefTest extends CamelTestSupport {

    public class SampleMockRoute extends RouteBuilder {

        public void configure() throws Exception {
            System.out.println("configure");
            from("direct:sampleInput")
                    .log("Received Message is ${body} and Headers are ${headers}")
                    //.to("http4://localhost:8983/test")
                    .pollEnrich("http4://localhost:8983/test", (exchange1, exchange2) -> {
                        return exchange1;
                    })
                    .log("after enrich ${body} ")
                    .to("mock:output");
        }
    }

    @Override
    public boolean isUseAdviceWith() {
        return true;
    }

    @BeforeEach
    public void beforeAll() throws Exception {
        AdviceWithRouteBuilder mockHttp4 = new AdviceWithRouteBuilder() {
            @Override
            public void configure() throws Exception {
                interceptSendToEndpoint("http4://localhost:8983/test")
                        .log("call MOCK HTTP").skipSendToOriginalEndpoint();

            }
        };
        context = new DefaultCamelContext();
        context.addRoutes(new SampleMockRoute());
        context.getRouteDefinitions().get(0).adviceWith(context, mockHttp4);
        template = context.createProducerTemplate();
    }

    @Test
    public void sampleMockTest() throws InterruptedException {
        try {
            context.start();
            String expected = "Hello";
            MockEndpoint mock = getMockEndpoint("mock:output");
            mock.expectedBodiesReceived(expected);
            String input = "Hello";
            template.sendBody("direct:sampleInput", input);
            mock.assertIsSatisfied();
            context.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

    标签: mocking apache-camel endpoint


    【解决方案1】:

    您可以尝试在 configure() 中使用 weavyByType。唯一的问题是它将用该路由中的以下模拟 url 替换所有 pollEnrich 模式。如果您的路线中只有一个 pollEnrich,这应该可以达到您的目的。

    weaveByType(PollEnrichDefinition.class).replace().to("mock:mock-url");

    您还可以尝试在您的路线中为特定 pollEnrich 设置一个 ID,如下所示。

    .pollEnrich("http4://localhost:8983/test", (exchange1, exchange2) -> {
                            return exchange1;
                        }).id("myPollEnrichId")
    

    完成后,您可以使用 weavyById 模拟特定的 pollEnrich。

    weaveById("myPollEnrichId").replace().to("mock:mock-url");

    【讨论】:

    • 谢谢,但是当我使用weaveByTypeweabeById 路由时不会调用聚合策略。只需转到模拟网址并忽略 (exchange1, exchange2) -> { return exchange1; }
    【解决方案2】:

    对于被替换路由没有调用聚合策略的问题困扰的人:你可以使用weaveByIdpollEnrich,但你还需要添加AggregationStrategy参数(见下文),否则不会调用它,因为它正在用另一个没有它的 pollEnrich 替换原来的 pollEnrich

    首先:在configure 方法中为您原来的pollEnrich 添加一个id:

    .pollEnrich("http4://localhost:8983/test", (exchange1, exchange2) -> {
                            return exchange1;
                        }).id("my-pollEnrich")
    

    第二:在测试中,使用weaveById将其发送到设置了聚合策略的模拟路由:

    AdviceWithRouteBuilder mockHttp4 = new AdviceWithRouteBuilder() {
            @Override
            public void configure() throws Exception {
                weaveById("my-pollEnrich").replace().pollEnrich("mock:my-pollEnrich-mock", (exchange1, exchange2) -> {
                    return exchange1;
                }).id("my-pollEnrich"); //set the same id, otherwise it won't find when executing "beforeEach" again
    
            }
    };
    

    如果你需要在路由中测试实际的聚合策略,最好的方法是为其创建一个单独的类并在测试中重用它。

    【讨论】:

      【解决方案3】:

      您可以将 pollEnrich 替换为 weaveBy... 有各种变体weaveByTypeweaveById等。

      如果您使用 weaveByType 并且路线中有多个 PollEnrich,则可以使用 selectFirst()selectLast() 进行选择等等

      替换可以由另一个端点完成,例如模拟端点,但出于测试目的,我发现使用处理器并直接设置所需的交换内容很方便,或者在需要时保持不变。

      下面是骆驼 3.5 的代码示例

          ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class);
              RouteReifier.adviceWith(mcc.getRouteDefinition("IdOfMyRoute"), mcc, new AdviceWithRouteBuilder() {
                  @Override
                  public void configure() {
                      weaveByType(PollEnrichDefinition.class).selectFirst().replace().processor((exchange) -> {
      
      });
                  }
              });
      

      【讨论】: