I had a test class which had a String isMockEndpointsAndSkip() { return ("*") }
for testing some stuff, and that made other classes complain with the following exception java.lang.IllegalArgumentException: Cannot advice route as there are no routes
.
quarkus-core
version: 2.16.9.Finalquarkus-camel-bom
version: 2.16.9.FinalI started changing the class with two AdviceWith
statements and attempted to run the tests, and one passes but the other one fails. By enabling debugging with quarkus.log.category."org.apache.camel".level=DEBUG
, I see that after the first test the Camel context seems to be taken down.
I have a test class that goes like this:
@QuarkusTest
public class DispatcherProcessorTest extends CamelQuarkusTestSupport {
@Inject
DispatcherProcessor dispatcherProcessor;
@Override
public boolean isUseAdviceWith() {
return true;
}
/**
* Tests that when a "recipient setting" doesn't contain an RBAC group's
* UUID, the exchange is sent to the {@link Routes#FETCH_USERS} route.
*/
@Test
void testSendFetchUsers() throws Exception {
// Create an exchange with an empty body.
final Exchange exchange = this.createExchangeWithBody("");
// Create a recipient settings object without the group's UUID.
final RecipientSettings recipientSettings = new RecipientSettings(
true,
true,
null,
new HashSet<>()
);
// Set the property that will be grabbed in the processor.
exchange.setProperty(ExchangeProperty.RECIPIENT_SETTINGS, List.of(recipientSettings));
// Assert that the exchange was sent to the correct route.
AdviceWith.adviceWith(this.context(), EngineToConnectorRouteBuilder.ENGINE_TO_CONNECTOR, a -> {
a.mockEndpointsAndSkip(String.format("direct:%s", Routes.FETCH_USERS));
a.mockEndpointsAndSkip(String.format("direct:%s", Routes.FETCH_GROUP));
});
this.startCamelContext();
this.context().start();
final MockEndpoint fetchUsersEndpoint = this.getMockEndpoint(String.format("mock:direct:%s", Routes.FETCH_USERS));
final MockEndpoint fetchGroupEndpoint = this.getMockEndpoint(String.format("mock:direct:%s", Routes.FETCH_GROUP));
fetchUsersEndpoint.expectedMessageCount(1);
fetchGroupEndpoint.expectedMessageCount(0);
this.dispatcherProcessor.process(exchange);
fetchUsersEndpoint.assertIsSatisfied();
fetchGroupEndpoint.assertIsSatisfied();
// Make sure that the exchange contains the "RecipientSettings" object
final List<Exchange> exchanges = fetchUsersEndpoint.getExchanges();
final Exchange sentExchange = exchanges.get(0);
final RecipientSettings sentRecipientSettings = sentExchange.getProperty(ExchangeProperty.CURRENT_RECIPIENT_SETTINGS, RecipientSettings.class);
Assertions.assertEquals(recipientSettings, sentRecipientSettings, "the recipient settings object was not properly set in the dispatcher");
}
/**
* Tests that when a "recipient setting" contains an RBAC group's UUID,
* the exchange is sent to the {@link Routes#FETCH_GROUP} route.
*/
@Test
void testSendFetchGroup() throws Exception {
// Create an exchange with an empty body.
final Exchange exchange = this.createExchangeWithBody("");
// Create a recipient settings object with the group's UUID.
final RecipientSettings recipientSettings = new RecipientSettings(
true,
true,
UUID.randomUUID(),
new HashSet<>()
);
// Set the property that will be grabbed in the processor.
exchange.setProperty(ExchangeProperty.RECIPIENT_SETTINGS, List.of(recipientSettings));
// Assert that the exchange was sent to the correct route.
AdviceWith.adviceWith(this.context(), EngineToConnectorRouteBuilder.ENGINE_TO_CONNECTOR, a -> {
a.mockEndpointsAndSkip(String.format("direct:%s", Routes.FETCH_USERS));
a.mockEndpointsAndSkip(String.format("direct:%s", Routes.FETCH_GROUP));
});
this.startCamelContext();
this.context().start();
final MockEndpoint fetchUsersEndpoint = this.getMockEndpoint(String.format("mock:direct:%s", Routes.FETCH_USERS));
final MockEndpoint fetchGroupEndpoint = this.getMockEndpoint(String.format("mock:direct:%s", Routes.FETCH_GROUP));
fetchUsersEndpoint.expectedMessageCount(0);
fetchGroupEndpoint.expectedMessageCount(1);
this.dispatcherProcessor.process(exchange);
fetchUsersEndpoint.assertIsSatisfied();
fetchGroupEndpoint.assertIsSatisfied();
// Make sure that the exchange contains the "RecipientSettings" object
final List<Exchange> exchanges = fetchGroupEndpoint.getExchanges();
final Exchange sentExchange = exchanges.get(0);
final RecipientSettings sentRecipientSettings = sentExchange.getProperty(ExchangeProperty.CURRENT_RECIPIENT_SETTINGS, RecipientSettings.class);
Assertions.assertEquals(recipientSettings, sentRecipientSettings, "the recipient settings object was not properly set in the dispatcher");
}
}
However, the second test fails with the same error message: java.lang.IllegalArgumentException: Cannot advice route as there are no routes
. I thought it had to do with the fact that I was "adviceing" the same route twice, but I saw in How do i unit test the same route multiple times using Apache Camel that this is perfectly fine.
What am I doing wrong?
After asking in the camel-quarkus
Zulip chat, the user "Christian Kalkhoff" pointed me at the solution. Essentially, they key to using AdviceWith
is to make sure that you are disabling the route builder:
@Override
public boolean isUseAdviceWith() {
return true;
}
@Override
public boolean isUseRouteBuilder() {
return false;
}
According to dkulp's "Apache Camel: Camel Test" page, you need to disable the route builder in order to give Apache Camel time to apply the advised routes to the context:
- Method name: boolean isUseRouteBuilder()
- Description: If the route builders from returned from createRouteBuilder() or createRouteBuilders() should be added to the CamelContext used in the test should be started. If the CamelContext use in the test should be automatically started before test methods are invoked. Override when using advice with and return true. This helps in knowing the adviceWith is to be used, and the CamelContext will not be started before the advice with takes place. This delay helps by ensuring the advice with has been property setup before the CamelContext is started.
I haven't been able to run ./mvnw clean test
on the project with this, though, because I end up suffering from the same error. In order to be able to do that, I still need to put @TestProfile(TestClassName.class)
in the test class's annotation:
- To force Quarkus JUnit Extension to restart the application (and thus also CamelContext) for a given test class, you need to assign a unique @io.quarkus.test.junit.TestProfile to that class. Check the Quarkus documentation for how you can do that. (Note that @io.quarkus.test.common.QuarkusTestResource has a similar effect.)
As stated in the documentation, the performance worsens, but at least I can run all the tests.