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;
}
}