001: package org.mockejb;
002:
003: import java.lang.reflect.*;
004:
005: import org.apache.cactus.*;
006:
007: /**
008: * Runs the test case on the server side under cactus or
009: * standalone on the client side. Concrete test cases extend this
010: * class.
011: *
012: * If "mockejb.cactus.mode" system property is set to true, the test case
013: * behaves as the Cactus' ServletTestCase, so it runs
014: * on the server.
015: * If the property is false or not set, Cactus is ignored completely and the test
016: * class runs on the client under JUnit.
017: * Subclasses can override <code>isCactusEnabled()</code> to use a different
018: * mechanism for turning cactus mode on and off.
019: *
020: * @author Alexander Ananiev
021: */
022: public class OptionalCactusTestCase extends ServletTestCase {
023:
024: /**
025: * Creates a new TestCase for the given test.
026: * @param testName test name
027: */
028: public OptionalCactusTestCase(String testName) {
029: super (testName);
030: }
031:
032: /**
033: * Tests if the test should run in Cactus mode. Cactus
034: * mode is turned on if the system property "mockejb.cactus.mode" is set
035: * to "true".
036: * Subclasses can implement different way of specifying Cactus mode.
037: *
038: * @return true if "mockejb.cactus" system property set to true
039: */
040: protected boolean isCactusMode() {
041: String cactusProp = System.getProperty("mockejb.cactus.mode");
042:
043: return (cactusProp != null && cactusProp
044: .equalsIgnoreCase("true"));
045:
046: }
047:
048: /**
049: * Tests if the test is being executed on the app server.
050: * @return true if the test runs on the app server
051: */
052: public boolean isRunningOnServer() {
053: return (this .request != null);
054: }
055:
056: /**
057: * Overrides the standard JUnit and Cactus method.
058: * This allows to
059: * turn the cactus off for this test class even though it continues
060: * to extend ServletTestCase.
061: * The method first checks if the test runs on the client, in
062: * which case it calls <code>runBareLocally</code>/
063: * If the test runs on the server, it calls "super" to
064: * delegate running the test to ServletTestCase
065: *
066: * @throws Throwable in case of any problems in the test
067: *
068: * @see junit.framework.TestCase#runBare()
069: */
070: public void runBare() throws Throwable {
071: // if we are called on the client
072: if (!isRunningOnServer()) {
073: runBareLocally();
074: }
075: // on the server
076: else {
077: super .runBare();
078: }
079:
080: }
081:
082: /**
083: * This method is called by <code>runBare</code> when it
084: * determines that the test is running locally (on the client).
085: * If the cactus is "on", this method simply calls "super".
086: * If the cactus is "off", it runs the code copied from
087: * JUnit, therefore disabling the override in Cactus.
088: *
089: * @throws Throwable in case of any problems in the test
090: */
091: protected void runBareLocally() throws Throwable {
092:
093: if (isCactusMode()) {
094: super .runBare();
095: } else {
096: setUp();
097: try {
098: runTestLocally();
099: } finally {
100: tearDown();
101: }
102: }
103: }
104:
105: /**
106: * Invokes the test method using reflection.
107: * Standard JUnit logic is duplicated here.
108: * Using this method instead of <code>runTest()</code> enforces
109: * that the test always runs locally (on the client). Cactus overrides <code>runTest()</code>
110: * to run the test remotely, so using a different name ensures that it does not run.
111: *
112: * @see junit.framework.TestCase#runTest()
113: *
114: * @exception Throwable if any exception is thrown
115: */
116: protected void runTestLocally() throws Throwable {
117: assertNotNull(getName());
118: Method runMethod = null;
119: try {
120: // use getMethod to get all public inherited
121: // methods. getDeclaredMethods returns all
122: // methods of this class but excludes the
123: // inherited ones.
124: runMethod = getClass().getMethod(getName(), null);
125: } catch (NoSuchMethodException e) {
126: fail("Method \"" + getName() + "\" not found");
127: }
128: if (!Modifier.isPublic(runMethod.getModifiers())) {
129: fail("Method \"" + getName() + "\" should be public");
130: }
131:
132: try {
133: runMethod.invoke(this , new Class[0]);
134: } catch (InvocationTargetException e) {
135: e.fillInStackTrace();
136: throw e.getTargetException();
137: } catch (IllegalAccessException e) {
138: e.fillInStackTrace();
139: throw e;
140: }
141: }
142:
143: }
|