在 Apache Camel 应用程序中,单元测试如何注入模拟端点来代替真实端点?

Posted

技术标签:

【中文标题】在 Apache Camel 应用程序中,单元测试如何注入模拟端点来代替真实端点?【英文标题】:In an Apache Camel application, how can unit tests inject mock endpoints in place of real ones? 【发布时间】:2015-06-17 08:39:29 【问题描述】:

我正在使用 Apache Camel 实现 message translator pattern,以使用来自 RESTful 端点的消息并将它们发送到 AMQP 端点。

封闭的应用程序基于 Spring Boot,因此我使用 Camel 的“spring-boot”组件来集成这两个框架。正如这个 spring-boot 链接中的文档所建议的那样,我在扩展 RouteBuilder@Configuration-annotated 类中实现了我的 Camel 路由:

@Component
public class MyRestToAmqpRouter extends RouteBuilder 

   @Override
   public void configure() throws Exception 

      from("jetty:http://my-restful-url")
         .process(exchange -> 
            // convert the message body from JSON to XML, take some 
            // incoming header values and put them in the outgoing
            // body, etc...
         ).to("rabbitmq://my-rabbitmq-url");

   


我的问题涉及如何在不需要实际的 RESTful 端点或配置的 RabbitMQ 代理的情况下对该翻译进行单元测试?我已经阅读了许多在线示例,以及 Camel in Action 一书...似乎单元测试 Camel 路线的典型方法是将路线剪切粘贴到您的单元测试,并将一个或多个端点 URL 替换为“mock:whatever”。

我猜 sorta 可以工作...但是它非常脆弱,并且您的测试套件无法识别以后有人在没有更新单元测试的情况下更改了真实代码。

我尝试使用模拟来调整一些基于 Spring 的单元测试示例,如下所示:

@RunWith(CamelSpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class)
public class MyRestToAmqpRouterTest extends AbstractJUnit4SpringContextTests 

    @Produce(uri = "jetty:http://my-restful-url")
    private ProducerTemplate fakeRest;

    @EndpointInject(uri = "rabbitmq://my-rabbit-url")
    private MockEndpoint fakeRabbit;

    @Test
    @DirtiesContext
    public void testRouter() throws InterruptedException 
        fakeRabbit.expectedMessageCount(1);
        fakeRest.sendBodyAndHeader("", "header-1", "some value");
        fakeRabbit.assertIsSatisfied();
    


我希望 Camel 从单元测试中获取这些端点 URL,将它们注册为模拟......然后在真实代码尝试使用这些 URL 时使用模拟而不是真实端点。

但是,我不确定这是否可行。当我在单元测试中使用真实 URL 时,我得到了 IllegalArgumentException,因为您显然无法将“真实”端点 URL 注入到 MockEndpoint 实例中(仅 URL 以“mock:”为前缀)。

当我在单元测试中使用“mock:...”端点 URL 时,它是没有用的,因为没有任何东西将它与被测类中的真实端点 URL 联系起来。因此,真正的端点 URL 永远不会被覆盖。当真正的代码被执行时,它只是像往常一样使用真正的端点(目标是能够在没有外部依赖于 RabbitMQ 的情况下进行测试)。

我在这里是否遗漏了一些真正基础的东西?似乎有一种方法可以让单元测试将假路由注入到这样的类中,以便被测代码甚至可以在没有意识到的情况下从真实端点切换到模拟端点。或者,我想我可以重构我的代码,以便将匿名 Processor 提升到一个独立的类......然后我可以独立于路由对它的翻译逻辑进行单元测试。但这似乎只是一个不完整的测试。

【问题讨论】:

【参考方案1】:

一些指示你可以做什么。

你可以再看一下Camel关于测试的书,注意使用advice with

http://camel.apache.org/advicewith.html

还有mockEndpointsAndSkip

http://camel.apache.org/mock.html

你也可以使用stub组件

http://camel.apache.org/stub

或者在你的路由中使用属性占位符,然后将 uris 配置为 mock/stub 等进行测试,并使用真实的进行生产

http://camel.apache.org/using-propertyplaceholder.html

【讨论】:

感谢克劳斯的详细回复(以及您在 Camel 上的工作!)。我最终能够组合出一个基于属性占位符的解决方案……尽管 Spring Boot 环境中的一些细节与老式的基于 XML 的 Spring(甚至是基于注释的没有 Boot 的 Spring)有些不同。并不是我在抱怨,但由于 Spring Boot 正在成为 Pivotal 新 Spring 开发的主要推荐方法,因此很高兴在文档中看到更多以 Boot 为中心的示例以及旧的 Spring 示例。 是的,我们还将关注并改进 Camel Boot / Spring Boot - 例如,您有时可以查看这些组件本身的单元测试,看看我们是如何做到的 - camel.apache.org/camel-boot

以上是关于在 Apache Camel 应用程序中,单元测试如何注入模拟端点来代替真实端点?的主要内容,如果未能解决你的问题,请参考以下文章

以 Apache Camel Exchange 作为参数的单元测试功能

[每日一学]apache camel|BDD方式开发apache camel|Groovy|Spock

使用cametestsupport进行camel单元测试,模板始终为null

Apache Camel - 调用 http 或 rest 调用(通过 Shiro Security 过滤)

Apache Camel - 调用 http 或 rest 调用(通过 Shiro Security 过滤)

Apache camel 错误处理如何与多播和事务一起使用