citrusframework / citrus

Framework for automated integration tests with focus on messaging integration
https://citrusframework.org
Apache License 2.0
458 stars 134 forks source link

Autowire test behaviors #617

Open rdeinum opened 5 years ago

rdeinum commented 5 years ago

User story

As a developer, I want test behaviors to be autowired so I can easily use Spring beans in my test behaviors.

Additional context

As the documentation about test behavior states behaviors are reusable test action templates. Therefore I am creating test behaviors based upon, in my case, the com.consol.citrus.dsl.runner.AbstractTestBehavior and populate them with groups of actions I would like to reuse in various tests. Some of these actions require me to pass them instances which I have setup as beans managed by Spring. One can access these beans through the Spring application context which is available via AbstractTestBehavior. Therefore I need to call some overload of the getBean method via org.springframework.context.ApplicationContext. But there are several disadvantages with this approach.

For starters it is very tedious to call this method every time I need access to some bean. I could of course solve this by introducing some methods which do the bean resolving for me, maybe even centralize this in some utility class which are prone to be overly large, not cohesive, and therefore simply not feasible from a maintenance perspective.

Another aproach would be to move the code away from the test behaviors to Spring beans which are managed and therefore subject to Spring dependency injection. But this is also not favorable, because of there nature, Spring beans should be kept stateless, while test behaviors are intended to be statefull. The Citrus sample project involving behaviors depicts this clearly by constructing a test behavior using the Builder design pattern. So should I be moving the code away from the test behaviors I will need to have somehow access to the current TestRunner inside my Spring beans and also introduce ways to conserve and pass allong other statefull data to and between beans. The involves yet other layers of complexity and code to maintain which I would rather stay away from, ever so since Citrus already facilitates creating action templates with test behavior.

Because of the named issues with the current interaction between test behaviors and beans I suggest test behaviors to be susceptible to autowiring by Spring. This concept is also in play when Citrus is combined with Cucumber, where Spring beans can be autowired in Cucumber step definition classes. The DefaultTestRunner already sets the Spring ApplicationContext on an applied behavior (see implementation applyBehavior method), so why not call applicationContext.getAutowireCapableBeanFactory().autowireBean(behavior) before executing the behavior?

svettwer commented 5 years ago

Hi!

Sounds like a good idea to me. I'd have to check whether the suggested applicationContext.getAutowireCapableBeanFactory().autowireBean(behavior) could come with unwanted side effects but on first sight, this could make things much easier. :+1:

BR, Sven