package hirondelle.fish.test; import java.io.FileNotFoundException; import javax.servlet.ServletException; import junit.framework.*; import hirondelle.web4j.Controller; import hirondelle.fish.test.doubles.FakeServletConfig; import hirondelle.fish.test.doubles.FakeServletContext; import hirondelle.web4j.config.TESTDateConverterImpl; import hirondelle.fish.main.visit.TESTVisit; import hirondelle.fish.main.member.TESTMember; import hirondelle.fish.main.member.TESTMemberAction; import hirondelle.fish.main.member.TESTMemberDAO; import hirondelle.fish.test.doubles.FakeDAOBehavior; import hirondelle.fish.main.member.MemberDAO; /** Runs all <a href="http://www.junit.org">JUnit</a> tests defined for this application. <P><span class='highlight'>To run the tests in the example app, you must perform two edits to reflect your environment</span>: <ul> <li>set the root directory of the web app in {@link #setRootDirectory()} <li>set the credentials for database access in {@link hirondelle.fish.test.doubles.FakeConnectionSrc} </ul> <P>In addition, these tests <b>require the database driver to be present on the classpath.</b> <P>The recommended style is to place test classes in the same directory as the classes being tested. Such a style will follow the package-by-feature approach, where all items related to a single feature are placed in a single directory - <em>including the unit tests</em>. <P>These tests are a development tool, and are not typically executed in a deployment environment. */ public final class TESTAll { /** Run all JUnit tests in the application. <P>This method calls {@link #initControllerIfNeeded()}. */ public static void main(String args[]) throws ServletException, FileNotFoundException { setRootDirectory(); initControllerIfNeeded(); String[] testCaseName = {TESTAll.class.getName()}; junit.textui.TestRunner.main(testCaseName); //you may want to set logging levels here } /** Alter a System property named {@value hirondelle.fish.test.doubles.FakeDAOBehavior#USE_FAKE_DAOS} <P>That system property will control whether or not an Action will use a fake DAO or a real DAO. See {@link MemberDAO#getInstance()} for an illustration. @param aToggle controls whether or not Actions should use fake DAOs. If <tt>true</tt>, then a System property named {@value hirondelle.fish.test.doubles.FakeDAOBehavior#USE_FAKE_DAOS} is added with value <tt>true</tt>; if <tt>false</tt>, then the same property is removed. */ public static void actionsUseFakeDAOs(boolean aToggle){ if( aToggle ) { System.setProperty(FakeDAOBehavior.USE_FAKE_DAOS, "true"); } else { System.clearProperty(FakeDAOBehavior.USE_FAKE_DAOS); } } /** Initialize the WEB4J Controller using a {@link FakeServletConfig}. <P><b>This method requires the database driver to be present on the classpath.</b> <P>This initialization will allow tests for Models, DAOs, and Actions to be run as if they are in the regular runtime enviroment. <P>This method can be called repeatedly. If called more than once, then it is a no-operation. Thus, this method can be called both by this test suite, and by the individual unit tests. This allows unit tests to run either one at a time, or as part of this suite. <P>Calling this method mimics the regular runtime environment by passing a {@link FakeServletConfig} to the {@link Controller#init(javax.servlet.ServletConfig)} method. This in turn uses a {@link hirondelle.fish.test.doubles.FakeConnectionSrc} for fetching connections without using JNDI. */ public static void initControllerIfNeeded() throws ServletException, FileNotFoundException { if (!fIsControllerInitialized) { initController(); } } /** Set a System property needed by fake objects to a hard-coded value. <P>This System property must be set when using the fake objects. An alternative to calling this method is to simply define a <tt>-D</tt> argument to the JRE. <P>See {@link FakeServletContext#ROOT_DIRECTORY} for more information. */ public static void setRootDirectory(){ System.setProperty(FakeServletContext.ROOT_DIRECTORY, "C:\\myname\\projects\\fish"); } /** Return a {@link TestSuite} for all unit tests in the application. */ public static Test suite() { TestSuite suite = new TestSuite("All JUnit Tests"); /* Model Objects. Some models will have a dependency on proper configuration of code tables (which means ensuring the Controller is initialized). */ suite.addTest(new TestSuite(TESTDateConverterImpl.class)); suite.addTest(new TestSuite(TESTVisit.class)); suite.addTest(new TestSuite(TESTMember.class)); /* Actions. Here, actions use fake DAOs in order to avoid side effects, and ensure easy repeatability. */ actionsUseFakeDAOs(true); suite.addTest(new TestSuite(TESTMemberAction.class)); /* DAOs. Tests both real and fake DAOs. Fake DAOs can be tested for various behaviors upon failure. Here, that behavior is controlled using various System properties. Testing the DAOs <i>last</i> is convenient, since those System settings will not affect later tests. */ suite.addTest(new TestSuite(TESTMemberDAO.class)); return suite; } // PRIVATE // private static boolean fIsControllerInitialized = false; private static void initController() throws ServletException, FileNotFoundException { Controller controller = new Controller(); controller.init(new FakeServletConfig()); fIsControllerInitialized = true; } }