我有一个RouteBuilder
子类,用于设置我的Camel路由。它由Spring构建。最初它看起来像这样:
@Override
public void configure() throws Exception {
from(...)
.process(...)
.to(...)
}
我想要做的是根据配置添加额外的端点路由。 Spring使用一个Properties文件来创建RouteBuilder
bean,其中一个字段是boolean addAnotherEndpoint
。如果此布尔值为true,我想添加另一个to
。如果它是假的,我希望它回归到它当前的行为。所以我改成了这个:
@Override
public void configure() throws Exception {
from(...)
.process(...)
.to(...)
.choice()
when(constant(addAnotherEndpoint)).to(...)
.endChoice();
}
虽然这似乎有所期望的行为,但我遇到了为它编写单元测试的问题(因为它从属性文件中提取了addAnotherEndpoint
的值,即使我是试图在我的测试中覆盖它)。有没有更好的方法来处理这个?我目前的方法会有任何意想不到的副作用吗?
修改
我正在使用CamelSpringTestSupport
子类进行测试(使用JUnit测试)。在@Before
方法中,我创建了一个AdviceWithRouteBuilder
,用模拟替换所有端点。在我的@Test
中,我试图覆盖从属性文件中获取的addAnotherEndpoint
的值:
@Test
public void testConditionalRouting() throws Exception {
context.start();
MyRouteBuilder routeBuilder = (MyRouteBuilder) applicationContext.getBean("myRouteBuilder");
routeBuilder.setAddAnotherEndpoint(true);
getMockEndpoint("myMockEndpoint").expectedMessageCount(1);
sendMockMessage();
assertMockEndpointsSatisfied();
context.stop();
}
有一个相应的测试将addAnotherEndpoint
设置为false
并断言收到了0条消息。问题是覆盖这个变量的值似乎并没有起作用。一个测试通过,另一个测试失败,具体取决于我的属性文件是否表示值应为true
或false
。这对我来说是在我覆盖设置之前构建路径(因此也是在上下文启动之前)。我检查了调试器并正确覆盖了 设置。它似乎没有任何影响。
编辑2:
来自我的AdviceWithRouteBuilder
:
@Override
public void configure() throws Exception {
replaceFromWith(MOCK_FROM_ENDPOINT);
interceptSendToEndpoint(FIRST_TO_ENDPOINT)
.skipSendToOriginalEndpoint().to(MOCK_FIRST_TO_ENDPOINT);
weaveById(MY_PROCESSOR_ENDPOINT).replace()
.to(MOCK_MY_PROCESSOR_ENDPOINT);
weaveById(SECOND_TO_ENDPOINT).replace()
.to(MOCK_SECOND_TO_ENDPOINT);
}
这将用模拟端点替换每个EIP。我有4个依赖于这些的测试,它们似乎按预期工作,唯一的问题是条件路由。
除了JUnit注释之外,我的测试类上唯一的注释是@Override
isUseAdviceWith()
(返回true)和createApplicationContext()
,它返回一个新的Spring Application Context。
我在没有context.start()
的情况下运行我的测试,并且唯一通过的是接收断言0消息的测试(如果路由未启动则有意义)。所以我不相信上下文是自动启动的。
答案 0 :(得分:1)
以下是最终工作的内容:
我的测试很好,但我不得不重新考虑如何构建自己的路线。发生了什么是在创建Spring上下文时,正在构建路由。它检查了当时addAnotherEndpoint
的值,并根据该值设置了constant
。但是boolean
是一个原始值,这意味着它是按值传递的。为什么这很重要?因为constant()
函数只是根据构建路径时的常量的值来设置路径。稍后通过Spring更改它没有任何影响因为已经读取了该值。我需要做的是让它将一个对象作为谓词传递,这样我以后就可以像bean一样操纵同一个对象了。
此外,我按照建议从choice()
更改为filter()
。这是成品:
@Override
public void configure() throws Exception {
from(...)
.process(...)
.to(...)
.choice()
when(myBooleanPredicate).to(...)
.endChoice();
}
我的自定义谓词可以通过Spring操作:
public class BooleanPredicate implements Predicate {
private boolean value;
@Override
public boolean matches(Exchange exchange) {
return value;
}
public void setValue(boolean value) {
this.value = value;
}
此BooleanPredicate
的内部value
设置为addAnotherPredicate
。每次路由运行时都会重新读取,因为BooleanPredicate
是通过引用传递的。
答案 1 :(得分:0)
我刚刚发现
.when(exchange-> foo()==true)
足够了。