R – Spring context tests can’t find config locations

junitspringspring-test

I have a large application spread across multiple Spring bean definition xml files. In my test suite I manually load up the XML files I need using a FileSystemXmlApplicationContext to perform the tests I want to run. This reduces test set up time and allows me to use the same exact configuration files that are used in production.

Now I'm trying to use Spring's transactional test base classes which take the config locations and load the context for me. For some reason when the application context is created Spring cannot find any of the config files. This is confusing because I run the test from the same working directory as when I load the config myself using FileSystemXmlApplicationContext. If I prepend all my config locations with "file:" the paths I specify in my test are found, but any files that are imported or referenced by beans defined in the config (e.g. properties files) cannot be found. What's the deal? Can I get tests that extend the spring context test classes to work the same as the ones where I create the context myself?

For example, creating the context like this works fine:

ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[] { "WEB-INF/services-context.xml"})

If I extend AbstractTransactionalDataSourceSpringContextTests the following does not find services-context.xml:

@Override
protected String[] getConfigLocations() {
   return new String[] { "WEB-INF/services-context.xml"};
}

This finds services-context, but the PropertyPlaceholderConfigurer defined in there fails to find it's properties files.

 @Override
 protected String[] getConfigLocations() {
    return new String[] { "file:WEB-INF/services-context.xml"};
 }

Best Answer

We put all of our Spring config and properties files in the classpath, which keeps things simple - we can just extend our test classes from a base class like:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
        "/spring/*.xml", 
        "/testSpring/*.xml" })
public abstract class AbstractIntegrationTest  {

Here, the paths are all paths in classpath.

If you don't want to do that, have you checked how you are referencing the properties files in your services-context.xml? I suspect that if you add file: to your context configuration, then you'll also need to add this to your property file reference. You could perhaps just use a separate test Spring config file to change the definition of your property placeholder, and place this at the end of your list of context files - its definitions will then override those defined in earlier files.