【问题标题】:Camel : Mock and return value from component in routeCamel:模拟并从路由中的组件返回值
【发布时间】:2017-03-31 23:19:28
【问题描述】:

我的服务有以下路线:

public void configure() {

    /*
     * Scheduled Camel route to produce a monthly report from the audit table. 
     * This is scheduled to run the first day of every month.
     */

    // @formatter:off
    from(reportUri)
        .routeId("monthly-report-route")
        .log("Audit report processing started...")
        .to("mybatis:updateProcessControl?statementType=Update")
        .choice()
            /*
             * If the rows updated is 1, this service instance wins and can run the report.
             * If the rows updated is zero, go to sleep and wait for the next scheduled run.  
             */
            .when(header("CamelMyBatisResult").isEqualTo(1))
                .process(reportDateProcessor)
                .to("mybatis:selectReport?statementType=SelectList&consumer.routeEmptyResultSet=true")
                .process(new ReportProcessor())
                .to("smtp://smtpin.tilg.com?to=" 
                        + emailToAddr 
                        + "&from=" + emailFromAddr )
                .id("RecipientList_ReportEmail")
        .endChoice()
    .end();
    // @formatter:on
}

当我尝试对此进行测试时,它给了我一个错误,指出骆驼无法自动创建组件 mybatis。我对测试骆驼路线没有经验,所以我不完全确定该去哪里。第一个 mybatis 调用更新了表中的一行,该行不在测试中,所以我想做一些事情,比如当端点被命中时,返回值为 1 的 CamelMyBatisResult 标头。第二个 mybatis 端点应该返回一个 hashmap(第一次测试为空,第二次填充)。我如何通过骆驼测试实施一种何时/然后的机制?我查看了模拟端点骆驼文档,但我不知道如何应用它并让它返回一个值到交换,然后继续路由(测试的最终结果是检查一封电子邮件或不发送附件)

编辑:尝试同时使用 replace().set* 方法并通过调用内联处理器替换 mybatis 端点:

@Test
public void test_reportRoute_NoResultsFound_EmailSent() throws Exception {
    List<AuditLog> bodyList = new ArrayList<>();
    context.getRouteDefinition("monthly-report-route").adviceWith(context, 
            new AdviceWithRouteBuilder() {
                @Override
                public void configure() throws Exception {
                    replaceFromWith(TEST);
                    weaveById("updateProcControl").replace()
                        .process(new Processor() {
                            @Override
                            public void process(Exchange exchange) throws Exception {
                                exchange.getIn().setHeader("CamelMyBatisResult", 1);
                            }
                        });
                    weaveById("selectReport").replace()
                        .process(new Processor() {
                            @Override
                            public void process(Exchange exchange) throws Exception {
                                exchange.getIn().setBody(bodyList);
                            }
                        });
                    weaveById("RecipientList_reportEmail").replace()
                        .to("smtp://localhost:8083"
                                +"?to=" + "test@test.com"
                                +"&from=" + "test1@test1.com");
                }
    });
    ProducerTemplate prod = context.createProducerTemplate();
    prod.send(TEST, exch);

    assertThat(exch.getIn().getHeader("CamelMyBatisResult"), is(1));
    assertThat(exch.getIn().getBody(), is(""));
}

到目前为止,header 仍然为 null,body 也是如此(TEST 变量是直接组件)

【问题讨论】:

  • 你能发布你得到的错误吗?堆栈跟踪?
  • 自动创建的东西并不是真正的问题;我想模拟这些端点并返回一个响应,因为它不是那些直接在测试中的端点,所以我并不真正关心创建 mybatis 组件
  • 在这种情况下,为每个 .to() 设置一个 .id() 然后拦截、替换。并设置硬编码的响应值。请参阅建议进行测试.. camel.apache.org/advicewith.html
  • @Souciance Eqdam Rashti 啊,好的,谢谢。在一个半相关的说明中,你知道我可以使用什么样的表达式通过 MockEndpoint.returnReplyBody 发送一个 hashMap 或一个列表? Simple 对象似乎不适合我想要做的事情
  • 它需要使用表达式,但我会改为做一个adviceWith,而是这样写:weaveById("yourid").replace().setBody(yourhashmap);

标签: java mocking apache-camel camel-test


【解决方案1】:

如果您想输入硬编码响应,则在您的路线上执行adviceWith 会更容易。见这里:http://camel.apache.org/advicewith.html

基本上,为每个端点添加一个 id 或.to()。然后你的测试执行一个adviceWith,然后用一些硬编码的响应替换那个.to()。它可以是地图、字符串或您想要的任何其他内容,它将被替换。例如:

context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() {
    @Override
    public void configure() throws Exception {
        // weave the node in the route which has id = bar
        // and replace it with the following route path
        weaveById("bar").replace().multicast().to("mock:a").to("mock:b");
    }
});

注意,文档中说您需要重写 isAdviceWith 方法并手动启动和停止 camelContext。

如果您遇到问题,请告诉我们。开始可能有点棘手,但一旦掌握了窍门,模拟响应实际上非常强大。

这里是一个例子,当你做adviceWith..时添加一个主体到简单的表达式中。

context.getRouteDefinition("yourRouteId").adviceWith(context, new AdviceWithRouteBuilder() {
  @Override
  public void configure() throws Exception {
    weaveById("yourEndpointId").replace().setBody(new ConstantExpression("whateveryouwant"
     ));
  }

});

【讨论】:

  • 所以我已经尝试了一段时间,没有设置标题,它跳过了路由的其余部分,或者至少每次我在断言中检查交换的标题时返回为空,将使用测试更新问题
  • 当您提到使用 setBody 插入哈希图时,我将如何从表达式中做到这一点?该方法接受一个表达式参数,我找不到任何关于如何插入在 setBody 调用之前创建的变量的资源
  • @jbailie1991,我已经用一个例子编辑了我的答案。
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
  • 2015-11-20
  • 1970-01-01
相关资源
最近更新 更多