Below is the latest version of something I posted a little while ago.
http://forum.springframework.org/sho...902&highlight=
You need to call initialize() in setup of each class (in a test suite), but the context is only loaded once if the list of context files never changes. And if list changes that is ok too; context will be loaded if the file list differs from previous test class.
I have found some posts that propose static initializations but this only works within one test class.
ContextTestCase will load context only once for entire test suite.
Other test classes will load a new application context.
Not if all classes in your test suite inherit from ContextTestCase and the context file list is the same in initialize() method call of each.
Here is latest version:
Code:
import java.util.StringTokenizer;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* A JUnit TestCase extension that simplifies integration testing by making
* available a Spring application context. This class short-circuits the
* 'set all instance variables null before every test method' mechanism in
* favor of loading Spring environment only once before executing any test
* methods.
*/
public class ContextTestCase extends TestCase
{
private static String[] contextFiles = null;
private static ApplicationContext context = null;
protected final Object getBean( String bean )
{
return context.getBean(bean);
}
protected final ApplicationContext getContext()
{
return context;
}
/**
* Alternate form to initialize/load context
* @param xmlFiles in comma delimited string
*/
protected final void initialize( String xmlFiles )
throws Exception
{
String[] contextFiles = toStringArray( xmlFiles );
initialize( contextFiles );
}
/**
* @param xmlFiles context files that specify objects available
* in Spring application environment.
*/
protected final void initialize( String[] xmlFiles )
throws Exception
{
synchronized (ContextTestCase.class) {
if( context == null || !same( xmlFiles, contextFiles ) ) {
contextFiles = xmlFiles;
context = new ClassPathXmlApplicationContext( xmlFiles ); // load context
StringBuffer msg = new StringBuffer("<<< CONTEXT LOADED >>> [");
for( int i = 0; i < xmlFiles.length; i++ ) {
if ( i > 0 ) { msg.append(" "); }
msg.append( xmlFiles[i] );
}
msg.append("] IN class='");
msg.append( this.getClass().getName() );
msg.append("'");
System.out.println( msg.toString() );
}
}
}
/*
* Are String arrays the same or different?
*/
private static boolean same( String[] files1, String[] files2 )
{
boolean ret = true;
ret = files1 != null && files2 != null && files1.length == files2.length;
// true if both not null & same length arrays
// loop stops if ret==false
for( int i = 0; ret && i < files1.length; i++ ) {
ret = files1[i].equals( files2[i] );
}
return ret;
}
/*
* Convert comma delimited string into String array.
*/
private static String[] toStringArray( String listing )
{
String[] ret = null;
StringTokenizer t = new StringTokenizer( listing, "," );
final int count = t.countTokens();
ret = new String[count];
for( int i = 0; i < count; i++ ) {
ret[i] = t.nextToken().trim();
}
return ret;
}
}
And your descendent class will have code something like this:
Code:
MyClass instanceRef = null;
public void setUp() throws Exception
{
initialize( "contextFile1.xml,contextFile2.xml" );
instanceRef = (MyClass)getBean("myClassBean");
}