0

We have a Spring Integration route using a Router with an expression. This expression is set in the yml file. I would like to create unit tests setting manually the value for this router attribute, but it doesn't seem to work.

Test

@Autowired
EventDrivenConsumer myrouter;
.....
((ExpressionEvaluatingRouter) myrouter.getHandler()).setPrimaryExpression(new SpelExpressionParser().doParseExpression("true"));

Part of the XML context

<int:router input-channel="catchweightExcluderChannel" expression="${rip.config.exclude_catchweight}" default-output-channel="productTransformerChannel">
    <int:mapping value="true" channel="catchWeightFilteringChannel" />
    <int:mapping value="false" channel="productTransformerChannel" />
</int:router>

But it seems my value overrided is not affecting the behaviour...it seems as once Spring reads the context, changing attributes of components does not affect their behaviour.

1 Answer 1

1

You can't change the property that way because expression is a ctor arg for the ExpressionEvaluatingRouter:

public class ExpressionEvaluatingRouter extends AbstractMessageProcessingRouter {

    public ExpressionEvaluatingRouter(Expression expression) {
        super(new ExpressionEvaluatingMessageProcessor<Object>(expression));
        setPrimaryExpression(expression);
    }

}

I think for your test use-case the @TestPropertySource would be the best solution:

@RunWith(SpringRunner.class)
@TestPropertySource(properties = "rip.config.exclude_catchweight:true")

UPDATE

but then why is there a mutator called setPrimaryExpression

The setPrimaryExpression() and its sibling getExpression() for visualization tools and logs to make expression-based components much cleaner for analysis. Since one components may have several expressions, we decided to distinguish a prime one and therefore that name for a setter.

The real hard work for expression evaluation is done there in the ExpressionEvaluatingMessageProcessor, which is ctor-based as well, as we see.

For your per method requirements I only can suggests to create ApplicationContext manually and call its setEnvironment(new MockEnvironment(). And already there you can populate a desired value for that expression in particular case.

You can't override that ctor-based initialization when your application context is already started.

Sign up to request clarification or add additional context in comments.

3 Comments

Oki, it's a constructor arg, but then why is there a mutator called setPrimaryExpression ?
About the TestPropertySource is a class level annotation, so to test both true and false values I need to create 2 test classes instead of 2 methods . So, although I can put DirtiesContext at method level, I can not set anything overriding the properties at method level ?
See an UPDATE in my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.