I have the following route in a spring boot application
@Slf4j
@Component
public class LogRoute extends RouteBuilder {
@Override
public void configure() {
from("direct:log")
.routeId("direct-log-route")
.log(LoggingLevel.INFO, "Message picked up by direct-log-route ${body}")
.split(body().tokenize("\n"))
.setProperty("originalBody", body())
.unmarshal()
.json(JsonLibrary.Jackson, LogEvent.class)
.log(LoggingLevel.INFO, "Message formatted as LogEvent ${body}")
.process(exchange ->
exchange.getIn()
.getBody(LogEvent.class)
.setEvent_object(exchange.getProperty(
"originalBody", String.class)))
.to("bean-validator://checks")
.log(LoggingLevel.INFO, "Validation completed successfully ${body}")
.to("jpa:test.log.LogEvent")
.log(LoggingLevel.INFO, "Inserted log event ${body.id}");
}
}
and have the following test
@CamelSpringBootTest
@EnableAutoConfiguration
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.NONE,
properties = {
"camel.springboot.java-routes-include-pattern=**/LogRoute*"
},
classes = {LogRoute.class}
)
@ActiveProfiles("test")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@DisableJmx
public class LogRouteTest {
@Produce("direct:log")
ProducerTemplate producerTemplate;
@EndpointInject("mock://checks")
MockEndpoint validationEndpoint;
@EndpointInject("mock:test.log.LogEvent")
MockEndpoint jpaMockEndpoint;
@Autowired
private CamelContext context;
@BeforeEach
public void setup() {
context.setTracing(true);
}
@Test
public void shouldAutowireProducerTemplate() {
assertNotNull(producerTemplate);
}
@Test
public void invalidJsonMessage() throws InterruptedException {
validationEndpoint.expectedMessageCount(0);
jpaMockEndpoint.expectedMessageCount(0);
CamelExecutionException camelExecutionException =
assertThrows(CamelExecutionException.class,
() -> producerTemplate
.sendBody(
"direct:log",
"msg"));
boolean condition = camelExecutionException.getCause() instanceof JsonParseException;
assertTrue(condition);
jpaMockEndpoint.assertIsSatisfied();
validationEndpoint.assertIsSatisfied();
}
@Test
public void validJsonWithNoContent() throws InterruptedException {
NotifyBuilder notify =
new NotifyBuilder(context).whenDone(1).create();
validationEndpoint.expectedMessageCount(1);
validationEndpoint.expectedBodyReceived();
validationEndpoint.expectedNoHeaderReceived();
validationEndpoint.setLog(true);
jpaMockEndpoint.expectedMessageCount(0);
CamelExecutionException camelExecutionException =
assertThrows(CamelExecutionException.class,
() -> producerTemplate
.sendBody("direct:log", "{}"));
List<Exchange> exchanges = jpaMockEndpoint.getExchanges();
System.out.println(">>>>>>>"+exchanges.size());
System.out.println(">>>>>>>"+context.getRegistry());
System.out.println(">>>>>>>"+context.getRegistry().toString());
System.out.println(">>>>>>>"+context.getRoutes());
System.out.println(">>>>>>>"+context.getEndpoints());
System.out.println(">>>>>>>"+context.getComponentNames());
System.out.println(">>>>>>>"+context.getEndpointRegistry());
System.out.println(">>>>>>>"+context.getRoutesSize());
System.out.println(">>>>>>>"+context.getTypeConverter());
System.out.println(">>>>>>>"+context.getValidatorRegistry());
validationEndpoint.assertIsSatisfied(100);
jpaMockEndpoint.assertIsSatisfied(100);
}
}
The intent of the second test is to verify that if a msg "{}" is sent to direct:log endpoint, it would go beyond the to(bean-validator://checks) endpoint and would fail on the second endpoint in the route as it happens when I try it in the real-time.
invalidJsonMessage() test verifies that the exception occurs at the first bean validator endpoint and hence validation mockendpoint should receive 0 messages.
validJsonWithNoContent() test defines 2 mock endpoints one for bean validator and the second for jpa component. It expects the validation endpoint to receive one message and jpa to receive 0 messages as it fails on this component.
When the test class is run, the first test invalidJsonMessage() passes but the second test validJsonWithNoContent() fails. Here are the logs
2023-09-09T14:26:38.032+02:00 INFO 42584 --- [ main] c.t.s.j.CamelSpringBootExecutionListener : CamelSpringBootExecutionListener before: class momentum.retail.security.auth0.streams.log.LogRouteTest.validJsonWithNoContent
2023-09-09T14:26:38.033+02:00 INFO 42584 --- [ main] c.t.s.j.CamelSpringBootExecutionListener : Initialized CamelSpringBootExecutionListener now ready to start CamelContext
2023-09-09T14:26:38.033+02:00 INFO 42584 --- [ main] o.a.c.t.s.j.CamelAnnotationsHandler : Starting CamelContext with name [camelContext].
2023-09-09T14:26:38.093+02:00 INFO 42584 --- [ main] o.a.c.support.LifecycleStrategySupport : Autowired property: validatorFactory on component: bean-validator as exactly one instance of type: jakarta.validation.ValidatorFactory (org.springframework.validation.beanvalidation.LocalValidatorFactoryBean) found in the registry
2023-09-09T14:26:38.100+02:00 INFO 42584 --- [ main] o.a.camel.component.jpa.JpaComponent : Using EntityManagerFactory found in registry with id [entityManagerFactory] org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@4c7b4a31
2023-09-09T14:26:38.100+02:00 INFO 42584 --- [ main] o.a.c.c.jpa.DefaultTransactionStrategy : Using TransactionManager found in registry with id [transactionManager] org.springframework.orm.jpa.JpaTransactionManager@38320819
2023-09-09T14:26:38.124+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel 4.0.0 (camel-1) is starting
2023-09-09T14:26:38.127+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Routes startup (started:1)
2023-09-09T14:26:38.128+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Started direct-log-route (direct://log)
2023-09-09T14:26:38.128+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel 4.0.0 (camel-1) started in 3ms (build:0ms init:0ms start:3ms)
2023-09-09T14:26:38.561+02:00 INFO 42584 --- [ main] direct-log-route : Message picked up by direct-log-route {}
2023-09-09T14:26:38.599+02:00 INFO 42584 --- [ main] direct-log-route : Message formatted as LogEvent LogEvent(id=null, logId=null, logDate=null, logType=null, description=null, ipAddress=null, clientName=null, event_object=null)
2023-09-09T14:26:38.601+02:00 INFO 42584 --- [ main] direct-log-route : Validation completed successfully LogEvent(id=null, logId=null, logDate=null, logType=null, description=null, ipAddress=null, clientName=null, event_object={})
2023-09-09T14:26:38.662+02:00 WARN 42584 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42804
2023-09-09T14:26:38.662+02:00 ERROR 42584 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: column "event_obj" is of type json but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 116
2023-09-09T14:26:38.667+02:00 ERROR 42584 --- [ main] o.a.c.p.e.DefaultErrorHandler : Failed delivery for (MessageId: B22C94B2D01F6BC-0000000000000001 on ExchangeId: B22C94B2D01F6BC-0000000000000001). Exhausted after delivery attempt: 1 caught: org.hibernate.exception.SQLGrammarException: could not execute statement [ERROR: column "event_obj" is of type json but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 116] [insert into "LOGS".log_event (client_name,description,event_obj,ip_address,log_date,log_id,log_type) values (?,?,?,?,?,?,?)]
Message History (source location and message history is disabled)
---------------------------------------------------------------------------------------------------------------------------------------
Source ID Processor Elapsed (ms)
direct-log-route/direct-log-ro from[direct://log] 264835460
...
direct-log-route/to2 jpa:test.log.Log 0
Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
org.hibernate.exception.SQLGrammarException: could not execute statement [ERROR: column "event_obj" is of type json but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 116] [insert into "LOGS".log_event (client_name,description,event_obj,ip_address,log_date,log_id,log_type) values (?,?,?,?,?,?,?)]
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:89) ~[hibernate-core-6.2.6.Final.jar:6.2.6.Final]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.3.jar:1.9.3]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursiv~[idea_rt.jar:na]
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) ~[junit-rt.jar:na]
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) ~[junit-rt.jar:na]
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) ~[junit-rt.jar:na]
Caused by: org.postgresql.util.PSQLException: ERROR: column "event_obj" is of type json but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 116
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2713) ~[postgresql-42.6.0.jar:42.6.0]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2401) ~[postgresql-42.6.0.jar:42.6.0]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:368) ~[postgresql-42.6.0.jar:42.6.0]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:498) ~[postgresql-42.6.0.jar:42.6.0]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:415) ~[postgresql-42.6.0.jar:42.6.0]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190) ~[postgresql-42.6.0.jar:42.6.0]
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152) ~[postgresql-42.6.0.jar:42.6.0]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-5.0.1.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-5.0.1.jar:na]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275) ~[hibernate-core-6.2.6.Final.jar:6.2.6.Final]
... 130 common frames omitted
>>>>>>>0
>>>>>>>org.apache.camel.support.DefaultRegistry@1c6ab85
>>>>>>>org.apache.camel.support.DefaultRegistry@1c6ab85
>>>>>>>[Route[direct://log -> null]]
>>>>>>>[direct://log, bean-validator://checks, mock://checks, mock://test.log.LogEvent, jpa://test.log.LogEvent]
>>>>>>>[bean-validator, direct, mock, jpa, bean, spring-event]
>>>>>>>EndpointRegistry for camel-1 [capacity: 1000]
>>>>>>>1
>>>>>>>org.apache.camel.impl.converter.DefaultTypeConverter@100d071
>>>>>>>ValidatorRegistry for camel-1 [capacity: 1000]
2023-09-09T14:26:38.673+02:00 INFO 42584 --- [ main] o.a.camel.component.mock.MockEndpoint : Asserting: mock://checks is satisfied
2023-09-09T14:26:48.678+02:00 WARN 42584 --- [ main] o.a.camel.component.mock.MockEndpoint : The latch did not reach 0 within the specified time
2023-09-09T14:26:48.718+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel 4.0.0 (camel-1) is shutting down (timeout:10s)
2023-09-09T14:26:48.723+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Routes stopped (stopped:1)
2023-09-09T14:26:48.724+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Stopped direct-log-route (direct://log)
2023-09-09T14:26:48.725+02:00 INFO 42584 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel 4.0.0 (camel-1) shutdown in 7ms (uptime:10s)
2023-09-09T14:26:48.730+02:00 INFO 42584 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-09-09T14:26:48.734+02:00 INFO 42584 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2023-09-09T14:26:48.736+02:00 INFO 42584 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2023-09-09T14:26:48.737+02:00 INFO 42584 --- [ main] m.r.s.auth0.streams.log.LogRouteTest : ********************************************************************************
2023-09-09T14:26:48.737+02:00 INFO 42584 --- [ main] m.r.s.auth0.streams.log.LogRouteTest : Testing done: validJsonWithNoContent (test.log.LogRouteTest)
2023-09-09T14:26:48.737+02:00 INFO 42584 --- [ main] m.r.s.auth0.streams.log.LogRouteTest : Took: 10s610ms (10610 millis)
2023-09-09T14:26:48.737+02:00 INFO 42584 --- [ main] m.r.s.auth0.streams.log.LogRouteTest : ********************************************************************************
2023-09-09T14:26:48.737+02:00 INFO 42584 --- [ main] c.t.s.j.CamelSpringBootExecutionListener : CamelSpringBootExecutionListener after: class test.log.LogRouteTest.validJsonWithNoContent
java.lang.AssertionError: mock://checks Received message count. Expected: <1> but was: <0>
Expected :<1>
Actual :<0>
<Click to see difference>
at org.apache.camel.component.mock.MockEndpoint.fail(MockEndpoint.java:1860)
at org.apache.camel.component.mock.MockEndpoint.assertEquals(MockEndpoint.java:1794)
at org.apache.camel.component.mock.MockEndpoint.doAssertIsSatisfied(MockEndpoint.java:448)
at org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied(MockEndpoint.java:426)
at test.log.LogRouteTest.validJsonWithNoContent(LogRouteTest.java:107)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
You can use AdviceWith to mock endpoints, by using @UseAdviceWith annotation on your test class, and then intercepting the bean-validator endpoint to send to mock endpoint. Note that you need to start the context if you are using AdviceWith.
Also, since you are expecting no headers in endpoint, you need to remove CamelInterceptedEndpoint header which is added while intercepting endpoint.
You need to change your mock endpoint to below, since you want to mock bean-validator endpoint