本文介绍了在 Apache Camel 应用程序中,单元测试如何注入模拟端点而不是真实端点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Apache Camel 实现一个 消息翻译器模式,以使用来自RESTful 端点并将它们转发到 AMQP 端点.

I am implementing a message translator pattern with Apache Camel, to consume messages from a RESTful endpoint and send them onward to an AMQP endpoint.

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

The enclosing application is based on Spring Boot, and so I'm using Camel's "spring-boot" component to integrate the two frameworks. As suggested by the documentation in this spring-boot link, I'm implementing my Camel route inside of a @Configuration-annotated class which extends RouteBuilder:

@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".

My question involves how to go about unit-testing this translation, without needing an actual RESTful endpoint or configured RabbitMQ broker? I've read many online examples, as well as the Camel in Action book... and it seems like the typical approach for unit testing a Camel route is to cut-n-paste the route into your unit test, and replace one or more endpoint URL's with "mock:whatever".

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

I guess that sorta works... but it's awfully brittle, and your test suite won't recognize when someone later changes the real code without updating the unit test.

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

I've tried to adapt some Spring-based unit testing examples with mocks, like this:

@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 时,使用模拟而不是真正的端点.

My hope was that Camel would take those endpoint URLs from the unit test, register them as mocks... and then use the mocks rather than the real endpoint when the real code tries to use those URLs.

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

However, I'm not sure that this is possible. When I use the real URLs in the unit test I get IllegalArgumentException's, because you apparently can't inject a "real" endpoint URL into a MockEndpoint instance (only URLs prefixed with "mock:").

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

When I do use a "mock:..." endpoint URL in my unit test, then it's useless because there's nothing tying it to the real endpoint URL in the class under test. So that real endpoint URL is never overridden. When the real code is executed, it just uses the real endpoint as normal (and the goal is to be able to test without an external dependency on RabbitMQ).

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

Am I missing something on a really fundamental level here? It seems like there would be a way for unit tests to inject fake routes into a class like this, so that the code under test could switch from real endpoints to mock ones without even realizing it. Alternatively, I suppose that I could refactor my code so that the anonymous Processor were elevated to a standalone class... and then I could unit test its translation logic independently of the route. But that just seems like an incomplete test.

推荐答案

一些指示你可以做什么.

Some pointers what you may do.

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

You can read the Camel book again about testing, and pay attention to using advice with

还有mockEndpointsAndSkip

你也可以使用stub组件

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

Or use property placeholders in your routes, and then configure the uris to be mock/stub etc for testing, and use the real ones for production

这篇关于在 Apache Camel 应用程序中,单元测试如何注入模拟端点而不是真实端点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 18:02