In this article, we will see how spring merges context configuration details declared on a test class and all of its super classes via annotation @ContextConfiguration
.
We will create a test class hierarchy where each class in the hierarchy declares @ContextConfiguration
. BaseContextConfiguration
will be the base class which FirstContextConfiguration
will extends which in turn will be extended by the test class SecondContextConfiguration
.
Spring will look for @ContextConfiguration
for the given test class and for all the super classes up in the hierarchy.
Any spring based test class must run with SpringJUnit4ClassRunner
which is responsible to build the test context. As SpringJUnit4ClassRunner
is instantiated it build a merged context configuration based on the annotations @ContextConfiguration
and @ContextHierarchy
. If we have declared @ContextConfiguration
in any of the test classes’s super class then spring will merge the context configuration details. When it is ready to prepare the test instance, it will use the merged context configuration to build the ApplicationContext
and then it will inject any dependencies declared as its members using @Autowired
annotation.
Below is the test class which has @ContextConfiguration
and it extends FirstContextConfiguration
which in turn contains @ContextConfiguration
annotation.
We have auto-wired Config
, Config1
and Config2
members. As you can see test class provides only Config2
in classes
attribute of @ContextConfiguration
. We will provide the other configuration classes in @ContextConfiguration
annotation declared by its super-classes. In verifyBeans()
, we make sure spring has successfully auto-wired the dependencies.
SecondContextConfiguration:
package com.javarticles.spring; import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=Config2.class) public class SecondContextConfiguration extends FirstContextConfiguration { @Autowired protected Config config; @Autowired protected Config1 config1; @Autowired protected Config2 config2; @Test public void verifyBeans() { assertNotNull(config); assertNotNull(config1); assertNotNull(config2); } }
Here are the other classes in the hierarchy.
FirstContextConfiguration:
package com.javarticles.spring; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(classes=Config1.class) public class FirstContextConfiguration extends SuperClassWithContextConfiguration { }
Here is the base class.
BaseContextConfiguration:
package com.javarticles.spring; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(classes=Config.class) public class BaseContextConfiguration { }
The configuration classes are very simple.
Config:
package com.javarticles.spring; import org.springframework.context.annotation.Configuration; @Configuration public class Config { }
Config1:
package com.javarticles.spring; import org.springframework.context.annotation.Configuration; @Configuration public class Config1 { }
Config2:
package com.javarticles.spring; import org.springframework.context.annotation.Configuration; @Configuration public class Config2 { }
Download the source code
This was an example of spring merging @ContextConfiguration and using it to build application context.