I am trying to perform a unit test for one of my routes in camel however I can't find a way to check the body I receive from my route and check if it is what is expected. How can I do this with or without mocks?
Route
@Component
public class MyRoute extends RouteBuilder {
@Override public void configure() throws Exception {
from("direct:MyRoute")
.routeId("MyRoute")
.marshal().json(JsonLibrary.Jackson)
.log("Marshal to \n${body}");
}
}
Test
public class MyRouteTest extends CamelTestSupport {
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new MyRoute();
}
@Test
public void testRoute() throws Exception {
NotifyBuilder notify = new NotifyBuilder(context).whenDone(1).create();
Map<String,Object> map = new LinkedHashMap<>();
map.put("name","your_name");
template.sendBody("direct:MyRoute", map);
assertTrue(notify.matchesWaitTime());
}
}
You can use AdviceWith
and weaveAddLast
to add for example mock:result
to end of a route. Then use the injected MockEndpoint to define assertions for the exchange. MockEndpoint comes with many handy methods that you can use to check validity of the exchange.
When using AdviceWith to modify routes for tests, remember to use the @UseAdviceWith annotation and start the CamelContext manually before each test. This is to avoid unnecessary restarts of adviced routes.
package com.example;
import org.apache.camel.CamelContext;
import org.apache.camel.EndpointInject;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.AdviceWith;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.apache.camel.test.spring.junit5.UseAdviceWith;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@CamelSpringBootTest
@UseAdviceWith
public class MySpringBootApplicationTest {
@Autowired
private CamelContext camelContext;
@Autowired
private ProducerTemplate producerTemplate;
@EndpointInject(uri = "mock:result")
private MockEndpoint resulMockEndpoint;
@Test
public void test() throws Exception {
resulMockEndpoint.expectedMessageCount(1);
resulMockEndpoint.message(0)
.body().isEqualTo("Hello world");
addMockEndpointAsLast("hello");
camelContext.start();
producerTemplate.sendBody("direct:hello", "world");
resulMockEndpoint.assertIsSatisfied();
}
MockEndpoint addMockEndpointAsLast(String routeId) throws Exception {
AdviceWith.adviceWith(camelContext, routeId, builder -> {
builder.weaveAddLast()
.to("mock:result")
;
});
return resulMockEndpoint;
}
}
If you want to further examine the exchange, you can get it from the exchanges list of MockEndpoint. Below is example on how to get body of first exchange as String.
String result = resulMockEndpoint.getExchanges().get(0)
.getMessage().getBody(String.class);
You can use ProducerTemplate.send
method which returns the resulting exchange. However instead of body of any type the method wants you to provide it with exchange object which you can create using DefaultExchange
class.
package com.example;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.support.DefaultExchange;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@CamelSpringBootTest
public class MySpringBootApplicationTest {
@Autowired
private CamelContext camelContext;
@Autowired
private ProducerTemplate producerTemplate;
@Test
void testWithoutMock(){
Exchange exchange = new DefaultExchange(camelContext);
exchange.getMessage().setBody("world");
Exchange resultExchange = producerTemplate.send("direct:hello", exchange);
assertEquals("Hello world", resultExchange.getMessage().getBody());
}
}
package com.example;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class MySpringBootRouter extends RouteBuilder {
@Override
public void configure() {
from("direct:hello")
.routeId("hello")
.setBody().simple("Hello ${body}")
.log("${body}")
;
}
}
Examples use Apache Camel version 3.20.2