Search code examples
unit-testingapache-cameljmsstub

Setting JMSMessageID on stubbed jms endpoints in camel unit tests


I have a route that I am testing. I use stub://jms:queue:whatever to send/receive messages and extending CamelTestSupport for my test classes. I am having an issue with one of the routes that has a bean that uses an idempotent repo to store messages by "message id" for which it reads and stores the JMSMessageID property from exchange.

The problem I run into is that I can't figure out a way to set this property on messages sent on stubbed endpoints. Every time the method that requires this prop is called, the id returns null and i have to handle it as a null pointer. I can do this but the cleanest approach would be to just set the header on the test message. I tried includeSentJMSMessageId=true on endpoint, I tried using sendBodyAndHeader on producer and passing "JMSMessageID", "ID: whatever" in arguments, doesn't appear to work? I read that the driver/connectionfactory is supposed to set the header, but I'm not too familiar with how/where to do this. And since I am using a stubbed end points, I'm not creating any brokers/connectionfactories in my uts.


Solution

  • So dont stud out the JMS component replace it with a processor and then add the preferred JMSMessageID in the processor.

    Something like this code:

    
      @Test
        void testIdempotency() throws Exception {
            mockOut.expectedMinimumMessageCount(1);
            //specify the route to test
            AdviceWithRouteBuilder.adviceWith(context, "your-route-name", enrichRoute -> {
                //replace the from with a end point we can call directly.
                enrichRoute.replaceFromWith("direct:start");
    
                //replace the jms endpoint with a processor so it can act as the JMS Endpoint.
                enrichRoute.weaveById("jms:queue:whatever").replace().process(new Processor() {
                    @Override
                    public void process(Exchange exchange) throws Exception {
                        //Set that ID to the one I want to test
                        exchange.getIn().setHeader("JMSMEssageID", "some-value-to-test");
                    }
                });
                // add an endpoint at the end to check if received a mesage
    
                enrichRoute.weaveAddLast().to(mockOut);
    
            });
            context.start();
            //send some message
            Map<String,Object> sampleMsg = getSampleMessageAsHashMap("REQUEST.json");
            //get the response
            Map<String,Object> response = (Map<String,Object>)template.requestBody("direct:start", sampleMsg);
            // you will need to check if the response is what you expected.
            // Check the headers etc.
            mockOut.assertIsSatisfied();
        }