Question

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"};
 }
Was it helpful?

Solution 2

In addition to overriding getConfigLocations I also overrode loadContext and used a trusty fileSystemXmlApplicationContext in there.

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

 @Override
 protected ConfigurableApplicationContext loadContext(String[] locations) throws Exception {
     return new FileSystemXmlApplicationContext(locations);
  }

OTHER TIPS

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.

Your config locations are relative URIs, and will be interpreted as such by the base test class, with the URI being resolved relative to the location of the test class itself. Try using fully qualified URIs, or use relative URI taking into account where the test class is.

Can't you use classpath XML factories like ClassPathXmlApplicationContext?

Another possible solution is to duplicate the services-config.xml and rename as services-config-test.xml and then put under classpath. The same thing goes for properties file.

ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[] { "WebRoot/WEB-INF/services-context.xml"})
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top