Step 1: Define Your JUnit Test Service.
Define a basic Java class called
TestService for executing JUnit tests. For simplicity's sake, assume that the name of the test class and any required parameters are passed in via a map. Your service should contain a method for executing a test and returning the results. In this case, it returns the results inside a
TestResultCollection class (which a later step explains).
Inside your executeTest() method, load the JUnit test class and create a JUnit TestSuite. The TestSuite will automatically inspect your class and figure out all the test cases and test methods that need to be run:
public class TestService {
public TestResultCollection executeTest(String testClass, Map params) {
// Create Test
TestSuite suite = loadTestSuite(testClass);
...
}
protected TestSuite loadTestSuite(String testClass) {
try {
Class c = Class.forName(testClass);
TestSuite suite = new TestSuite(c);
return suite;
} catch (Exception e) {
throw new ApplicationException(e);
}
}
}
If an error occurs during class loading, you can propagate this back using some sort of standard application exception. This example communicates problems using a RuntimeException called ApplicationException.
Step 2: Provide a Mechanism to Pass Parameters to Tests.
Sometimes your tests are context sensitive and rely on user-supplied parameters. However, because the test class is class-loaded dynamically, there is no way to pass the parameters into the tests. One technique to manage this is to load any parameters into a
ThreadLocal-backed cache, which you can access from within the tests.
If you don't have one already, define a ThreadLocal-backed ApplicationContext object for storing parameters:
public abstract class ApplicationContext {
protected static ThreadLocal context = new ThreadLocal() {
public java.lang.Object initialValue() {
return new HashMap();
}
};
public static Map get() {
return (Map) context.get();
}
public static void close() {
Map map = (Map) context.get();
map.clear();
context.set(null);
}
}
Inside your test service, ensure that the ApplicationContext is populated prior to test execution and cleaned up at the end. You don't want short-lived parameter data hanging around in memory any longer than necessary:
public TestResultCollection executeTest(String testClass, Map params) {
try {
// initialise context
ApplicationContext.get().putAll(params);
// Create Test
TestSuite suite = loadTestSuite(testClass);
...
} finally {
ApplicationContext.close();
}
}