摘要:
我在尝试测试模板化路由时,从我的junit中得到一个IllegalArgumentException,该模板化路由是根据我在第二个RouteBuilder类中创建的模板构建的。
你可以在CreateTemplate类中看到,我尝试使用第三个模板参数来设置TO文件生成器的.id()字符串。这样做是为了我可以在junit中找到(通过weaveById)并模拟这个生成器。但是,似乎id设置不正确,weaveById失败了。
如果我直接创建路由,我的意思是,不通过模板,这工作得很好,我可以用weaveById()方法模拟生产者。
使用Spring保护套2.7.0、Camel 3.16.0和openjdk-11。
我错过了什么?谢谢你的帮助。
注意:我确实找到了一个变通方法,那就是使用weaveByType()。这在junit中被注解掉了,但是工作正常。但是我仍然想知道为什么weaveById()在这里不工作。
问题详细信息与代码:
junit测试类:
package com.jvh.routes;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
@SpringBootTest
@CamelSpringBootTest
@UseAdviceWith
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class RouteTest {
@Autowired
private CamelContext camelContext;
@Autowired
private ProducerTemplate producerTemplate;
@EndpointInject("mock:endpointMock")
private MockEndpoint mockEndpoint;
@BeforeEach
public void setup() throws Exception {
mockEndpoint.reset();
AdviceWith.adviceWith(camelContext, "my-test-file-route", routeBuilder -> {
routeBuilder.replaceFromWith("direct:start");
routeBuilder.weaveById("my-internal-route-id").replace().to(mockEndpoint); // fails
//routeBuilder.weaveByType(ToDefinition.class).replace().to(mockEndpoint); // works
routeBuilder.setLogRouteAsXml(false);
});
camelContext.start();
}
@AfterEach
public void tearDown() {
camelContext.stop();
}
@Test
void test_processMessageToRestApi_Ok() throws Exception {
final String testMsg = "{ test msg }";
// Expect output file endpoint mock to receive 1 message
mockEndpoint.expectedMessageCount(1);
mockEndpoint.expectedBodiesReceived(testMsg);
// Message body
producerTemplate.sendBody("direct:start", testMsg);
mockEndpoint.assertIsSatisfied();
}
}
模板创建类:
package com.jvh.routes;
import org.apache.camel.LoggingLevel;
import org.apache.camel.Ordered;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class CreateTemplate extends RouteBuilder {
@Override
public int getOrder() {
return Ordered.HIGHEST; // required to ensure the template is created first
}
@Override
public void configure() {
routeTemplate("myTemplateId")
.templateParameter("input-directory-param-id")
.templateParameter("output-directory-param-id")
.templateParameter("route-id-param-id")
.from("file:{{input-directory-param-id}}")
.log(LoggingLevel.INFO, log, "--> got file ${header.CamelFileName}")
.to("file:{{output-directory-param-id}}")
.id("{{route-id-param-id}}") // set id here to be able to mock this producer
.log(LoggingLevel.INFO, log, "--> done");
}
}
模板化路由创建类:
package com.jvh.routes;
import org.apache.camel.CamelContext;
import org.apache.camel.Ordered;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.builder.TemplatedRouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CreateRoute extends RouteBuilder {
@Autowired
private CamelContext camelContext;
@Override
public int getOrder() {
return Ordered.LOWEST; // route created after the template
}
@Override
public void configure() throws Exception {
final String routeId = TemplatedRouteBuilder.builder(camelContext, "myTemplateId")
.routeId("my-test-file-route")
.parameter("input-directory-param-id", "input-directory")
.parameter("output-directory-param-id", "output-directory")
.parameter("route-id-param-id", "my-internal-route-id") // parameter to set the producer id
.add();
log.info("Route {} created from template", routeId);
}
}
运行junit测试时抛出的异常:
java.lang.IllegalArgumentException: There are no outputs which matches: my-internal-route-id in the route: Route(my-test-file-route)[From[direct:start] -> [Log[--> got file ${header.CamelFileName}], To[file:{{output-directory-param-id}}], Log[--> done]]]
at org.apache.camel.builder.AdviceWithTasks$1.task(AdviceWithTasks.java:226)
at org.apache.camel.builder.AdviceWith.doAdviceWith(AdviceWith.java:222)
at org.apache.camel.builder.AdviceWith.adviceWith(AdviceWith.java:75)
at com.jvh.routes.RouteTest.setup(RouteTest.java:38)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
<snip...>
junit运行的一些相关调试日志:
<snip...>
2022-05-23 16:36:58.535 DEBUG 10916 --- [ main] o.a.camel.spring.SpringCamelContext : onApplicationEvent: org.springframework.test.context.event.AfterTestMethodEvent[source=[DefaultTestContext@50fe837a testClass = RouteTest, testInstance = com.jvh.routes.RouteTest@510da778, testMethod = test_processMessageToRestApi_Ok@RouteTest, testException = java.lang.IllegalArgumentException: There are no outputs which matches: my-internal-route-id in the route: Route(my-test-file-route)[From[direct:start] -> [Log[--> got file ${header.CamelFileName}], To[file:{{output-directory-param-id}}], Log[--> done]]], mergedContextConfiguration = [WebMergedContextConfiguration@3a62c01e testClass = RouteTest, locations = '{}', classes = '{class com.jvh.TestApp}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@1187c9e8, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16aa8654, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@61eaec38, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@31920ade, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@16b2bb0c, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@5ae50ce6], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]]
2022-05-23 16:36:58.535 DEBUG 10916 --- [ main] tractDirtiesContextTestExecutionListener : After test method: context [DefaultTestContext@50fe837a testClass = RouteTest, testInstance = com.jvh.routes.RouteTest@510da778, testMethod = test_processMessageToRestApi_Ok@RouteTest, testException = java.lang.IllegalArgumentException: There are no outputs which matches: my-internal-route-id in the route: Route(my-test-file-route)[From[direct:start] -> [Log[--> got file ${header.CamelFileName}], To[file:{{output-directory-param-id}}], Log[--> done]]], mergedContextConfiguration = [WebMergedContextConfiguration@3a62c01e testClass = RouteTest, locations = '{}', classes = '{class com.jvh.TestApp}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@1187c9e8, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16aa8654, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@61eaec38, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@31920ade, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@16b2bb0c, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@5ae50ce6], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]], class annotated with @DirtiesContext [true] with mode [AFTER_EACH_TEST_METHOD], method annotated with @DirtiesContext [false] with mode [null].
2022-05-23 16:36:58.535 DEBUG 10916 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@15515c51, started on Mon May 23 16:36:49 EDT 2022
2022-05-23 16:36:58.535 DEBUG 10916 --- [ main] o.a.camel.spring.SpringCamelContext : onApplicationEvent: org.springframework.context.event.ContextClosedEvent[source=org.springframework.web.context.support.GenericWebApplicationContext@15515c51, started on Mon May 23 16:36:49 EDT 2022]
2022-05-23 16:36:58.543 DEBUG 10916 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647
2022-05-23 16:36:58.543 DEBUG 10916 --- [ main] o.a.c.main.SimpleMainShutdownStrategy : Shutdown called
2022-05-23 16:36:58.545 DEBUG 10916 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
2022-05-23 16:36:58.545 DEBUG 10916 --- [ main] o.s.t.c.w.ServletTestExecutionListener : Resetting RequestContextHolder for test context [DefaultTestContext@50fe837a testClass = RouteTest, testInstance = com.jvh.routes.RouteTest@510da778, testMethod = test_processMessageToRestApi_Ok@RouteTest, testException = java.lang.IllegalArgumentException: There are no outputs which matches: my-internal-route-id in the route: Route(my-test-file-route)[From[direct:start] -> [Log[--> got file ${header.CamelFileName}], To[file:{{output-directory-param-id}}], Log[--> done]]], mergedContextConfiguration = [WebMergedContextConfiguration@3a62c01e testClass = RouteTest, locations = '{}', classes = '{class com.jvh.TestApp}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@1187c9e8, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16aa8654, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@61eaec38, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@31920ade, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@16b2bb0c, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@5ae50ce6], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false, 'org.springframework.test.context.support.DependencyInjectionTestExecutionListener.reinjectDependencies' -> true]].
<snip...>
1条答案
按热度按时间9gm1akwq1#
WeaveByID正在特定路由的上下文中编织节点(即终结点)。
给定路线:
您可以执行:
在您的示例中,您正在编织“my-internal-route-id”,这是一个路由,而不是端点