Consider the scenario where you need to override certain properties across the integration tests
User class with name and hobby
PropertySources :
NameHobbyPropertySource
HobbyOnlyPropertySource
And this is your default context initializer for your application (that uses NameHobby property source)
i.e. your special test case should run with overridden hobby from HobbyOnlyPropertySource. You can achieve this using inheritInitializers as follows,
but this will not work because, By default the initializers of the derived class gets called and then the base class's initializers are called.
To override this behaviour, BOTH the initializer should implement Ordered interface and define an order.
Whichever one wants to run later should be given higher order. You can also try @Order annotation for the same.
Lets say MainApplicationContextInitializer is from third party lib, and it doesn't implement or annotated with Order, then this wouldn't work. So have a wrapper over the third party initializer and annotate it with @Order.
and your subset application context initializer should also be ordered
Refer :
User class with name and hobby
PropertySources :
NameHobbyPropertySource
public class NameHobbyPropertySource extends PropertySource<properties> { static Properties source = new Properties(); public NameHobbyPropertySource(String name) { super(name, source); source.setProperty("name", "chinnu"); source.setProperty("hobby", "cycling"); } @Override public Object getProperty(String key) { return getSource().get(key); } }
HobbyOnlyPropertySource
public class HobbyOnlyPropertySource extends PropertySource<properties> { static Properties source = new Properties(); public HobbyOnlyPropertySource(String name) { super(name, source); source.setProperty("hobby", "running"); } @Override public Object getProperty(String key) { return getSource().get(key); } }
And this is your default context initializer for your application (that uses NameHobby property source)
public class MainApplicationContextInitializer implements ApplicationContextInitializer<configurableapplicationcontext> { public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("Main initializer called"); NameHobbyPropertySource nameHobbyPropertySource = new NameHobbyPropertySource("name-hobby"); applicationContext.getEnvironment().getPropertySources().addFirst(nameHobbyPropertySource); } }Say your BaseIntegrationTest is configured with initializer that has NameHobbyPropertySource
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(initializers = { MainApplicationContextInitializer.class }, locations = { "classpath:application-context.xml" }) public abstract class BaseApplicationTest { }but you want to override this for only one test class.
i.e. your special test case should run with overridden hobby from HobbyOnlyPropertySource. You can achieve this using inheritInitializers as follows,
public class SubSetApplicationContextInitializer implements ApplicationContextInitializer<configurableapplicationcontext> { public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("Subset initializer called"); HobbyOnlyPropertySource hobbyOnlyPropertySource = new HobbyOnlyPropertySource( "hobby"); applicationContext.getEnvironment().getPropertySources() .addFirst(hobbyOnlyPropertySource); } }
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(initializers = { SubSetApplicationContextInitializer.class }, inheritInitializers = true) public class ApplicationTest extends BaseApplicationTest {
but this will not work because, By default the initializers of the derived class gets called and then the base class's initializers are called.
To override this behaviour, BOTH the initializer should implement Ordered interface and define an order.
Whichever one wants to run later should be given higher order. You can also try @Order annotation for the same.
Lets say MainApplicationContextInitializer is from third party lib, and it doesn't implement or annotated with Order, then this wouldn't work. So have a wrapper over the third party initializer and annotate it with @Order.
@Order(0) public class WrapperMainApplicationContextInitializer extends MainApplicationContextInitializer{ }And so the BaseApplicationTest should now use this wrapper,
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(initializers = { WrapperMainApplicationContextInitializer.class }, locations = { "classpath:application-context.xml" }) public abstract class BaseApplicationTest { }
and your subset application context initializer should also be ordered
public class SubSetApplicationContextInitializer implements ApplicationContextInitializer<configurableapplicationcontext>, Ordered { public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("Subset initializer called"); HobbyOnlyPropertySource hobbyOnlyPropertySource = new HobbyOnlyPropertySource( "hobby"); applicationContext.getEnvironment().getPropertySources() .addFirst(hobbyOnlyPropertySource); } public int getOrder() { return 1; } }
Refer :
- MainApplicationContextInitializer (that is not ordered)
- WrapperMainApplicationContextInitializer that makes the MainApplicationContextInitializer ordered
- SubSetApplicationContextInitializer that overrides certain properties
- BaseApplicationTest & ApplicationTest -> Test case that confirms that the overriding of properties succeeded
No comments:
Post a Comment