Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
405 views
in Technique[技术] by (71.8m points)

java - How to mock AMQP consumers in Camel testing?

Say I have the following route:

from(rabbitMQUri)
    .to(myCustomerProcessor)
    .choice()
        .when(shouldGotoA)
            .to(fizz)
        .when(shouldGotoB)
            .to(buzz)
        .otherwise()
            .to(foo);

Let's pretend that myCustomProcessor tunes shouldGotoA and shouldGotoB according to the message consumed from RabbitMQ.

I would like to unit test 3 scenarios:

  1. A "fizz" message is consumed and shouldGotoA is set to true, which executes the first when(...).
  2. A "buzz" message is consumed and shouldGotoB is set to true, which executes the second when(...).
  3. A "foo" message is consumed and the otherwise() is executed.

My question is: how do I mock/stub the RabbitMQ endpoint so that the route executes as it normally will in production, but so that I don't have to actually connect the test to a RabbitMQ server? I need some kind of "mock message" producer.

A code example or snippet would be extremely helpful and very much so appreciated!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is one way of putting together a suitable test.

Firstly define an empty Camel Context with just a ProducerTemplate in it:

<camel:camelContext id="camelContext">
   <camel:template id="producerTemplate" />
</camel:camelContext>

I do this so that when I execute the test, I can control which routes actually start as I don't want all my routes starting during a test.

Now in the test class itself, you'll need references to the producer template and Camel Context. In my case, I'm using Spring and I autowire them in:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/spring/spring-test-camel.xml" })
public class MyTest {

    @Autowired
    private ProducerTemplate producerTemplate;

    @Autowired
    private CamelContext camelContext;

In the test itself, replace the RabbitMQ/ActiveMQ/JMS component in the context with the seda or direct component. eg replace all JMS calls with a seda queue.

camelContext.removeComponent("jms");
camelContext.addComponent("jms", this.camelContext.getComponent("seda"));
camelContext.addRoutes(this.documentBatchRouting);

Now whenever you are reading or writing to a JMS URI, it is actually going to a seda queue. This is similar to injecting a new URI into the component but take less configuration and allows you to add new endpoints to the route without worrying about remembering to inject all the URIs.

Finally in the test, use the the producer template to send a test message:

producerTemplate.sendBody("jms:MyQueue", 2);

You're route should then execute and you can test your expectations.

Two things to note are:

  1. Your transaction boundaries may change, especially if you replace JMS queues with a direct component

  2. If you are testing several routes, you'll have to be careful to remove the route from the Camel Context at the end of the tests for that route.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...