Start Turbine in standalone mode

In order to test certain code that is using some of Turbine's services and singletons, it may be required to have Turbine running. Turbine started without a servlet container is considered running in standalone mode. The javadocs for TurbineConfig have more information but below is how to start Turbine in standalone mode.

TurbineConfig config = null;
config = new TurbineConfig("../",
                           "/conf/test.TurbineResources.properties");
config.init();

So our test case needs to start Turbine, run our tests, and stop Turbine. Stopping Turbine is easy since the objects are destroyed when the test case terminates. There are two ways to write test cases with Turbine running standalone. The first method is to define a base class that starts up Turbine in a static initializer. Then all your test cases that need Turbine running should descend this base test case.

package org.mycompany.newapp.test;

import junit.framework.TestCase;
import org.apache.turbine.util.TurbineConfig;
import org.apache.turbine.util.StringUtils;

/**
 Base test case used to start Turbine in standalone mode.
 */
public class TurbineStandaloneTestCase extends TestCase
{
    /*
    Configuration object to run Turbine outside a servlet container
    ( uses turbine.properties )
    */
    private static TurbineConfig config = null;
    
    /**
    Sets up TurbineConfig using the system property:
    <pre>turbine.properties</pre>
    */
    static
    {
        try
        {
	   config = new TurbineConfig( "..",
               System.getProperties().getProperty(
                  "turbine.properties",
                  "/conf/TurbineResources.properties" ) );
	   config.init();
        }
        catch (Exception e)
        {
            fail(StringUtils.stackTrace(e));
        }
    }

    public TurbineStandaloneTestCase( String name )
    {
        super( name );
    }
}

The base class test case method of starting Turbine has one drawback. If you have many test cases that descend TurbineStandaloneTestCase, each one will start Turbine, run some tests, and stop Turbine. This may slow down the testing process, especially when the unit tests are automated. The second method uses the TestSetup decorator provided by JUnit to start Turbine for a set of test cases. In this case we create an AllTests class which runs the test cases for us.

package org.mycompany.newapp.test;

import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.extensions.TestSetup;
import junit.framework.Test;

import org.apache.turbine.util.TurbineConfig;
import org.apache.turbine.util.StringUtils;

/**
 Runs all the unit tests for the current package.
 */
public class AllTests extends TestCase
{
    public AllTests(String name)
    {
        super(name);
    }

    public static Test suite()
    {
        /* These are tests that need Turbine running */

        TestSuite tsuite = new TestSuite();
        tsuite.addTest(test1Test.suite());
        tsuite.addTest(test2Test.suite());
        tsuite.addTest(test3Test.suite());

        TestSetup wrapper= new TestSetup(tsuite)
        {
            private TurbineConfig config = null;
            public void setUp()
            {
                try
                {
                    config = new TurbineConfig("../",
                       System.getProperties().getProperty(
                          "turbine.properties",
                          "/conf/test.TurbineResources.properties") );
                    config.init();
                }
                catch (Exception e)
                {
                    fail( StringUtils.stackTrace(e) );
                }
            }
        };

        TestSuite realSuite = new TestSuite();

        /* These are tests that don't need Turbine started */
        
        realSuite.addTest(test4Test.suite());
        realSuite.addTest(test5Test.suite());

        realSuite.addTest(wrapper);
        return realSuite;
    }
}

The AllTests class creates a test suite containing the tests that require Turbine to be started. Then a TestSetup wrapper is created around that suite of tests. A return suite is built with test 4 and 5 that do not require Turbine running. The wrapper suite containing the decorator and tests 1, 2, and 3 are then added to the return suite. The order the test cases will run is: 4, 5, 1, 2, 3. This now ensures that Turbine is started once for tests 1, 2 and 3. The drawback to this method is you cannot run one test case alone, you must always run all the tests. The first method, since Turbine is started for each case, you can run each test individually.