<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC 
    "-//APACHE//DTD Documentation V2.0//EN" 
    "http://forrest.apache.org/dtd/document-v20.dtd">
<document>
    <header>
        <title>Testing Controls</title>
    </header>
    <body>
    <section id="overview">
        <title>Overview</title>
        <p>
        A Beehive <a href="overview.xml">Control</a> can be tested either inside of an application 
        container or outside in a standalone Java environment.  The latter can be particularly useful
        running unit tests or during test driven development (TDD).  This document describes how to unit
        test a Beehive Control using JUnit.
        </p>
    </section>
    <section id="container">
        <title>The JUnit Controls Container</title>
        <p>
        The Controls JAR file <code>beehive-controls.jar</code> provides build time, run time, and test time
        support for developing Controls.  This makes it very easy to begin unit testing Controls that 
        are built as part of an application.  Out of the box, Controls provides integration into the 
        <a href="site:junit">JUnit</a> test framework via the 
        <a href="apidocs/javadoc/org/apache/beehive/controls/test/junit/ControlTestCase.html">ControlTestCase</a>
        base class.  This base class provides a Control <em>container</em> that hosts a Control for the duration
        of a Control test.  It also provides help in instantiating a Control declaratively via the 
        <a href="apidocs/javadoc/org/apache/beehive/controls/api/bean/Control.html">@Control</a> annotation.  
        </p>
        <p>
        To author a JUnit Controls test using the base class, the test case should be declared as:
        </p>
        <source>
public class FooTest
    extends ControlTestCase {   
...
}
        </source>
        <p>
        For each test case with a name method matching the JUnit naming convention <em>test*</em>, the 
        JUnit container will start and stop the 
        <a href="apidocs/javadoc/org/apache/beehive/controls/test/junit/ControlTestCase.html">ControlTestContainerContext</a>.
        The <code>beginContext</code> method will be called at the beginning of each test in the <code>setUp()</code>
        method, and the <code>endContext</code> method will be called at the end of each test in the <code>tearDown()</code>
        method.  This will simulate a <em>interaction lifetime</em> with the control where multiple Control instances can 
        be invoked multiple times.  The Control will hold any resources it acquires for the duration of the test method.  
        As an example, this begin / end Context lifetime represents the same lifetime as that for a single HttpServletRequest 
        in the web tier.  Any resources loaded from the <code>ControlTestContainerContext</code> are loaded from the current
        thread's context class loader.
        </p>
        <p>
        For a single test, once the <code>ControlTestContainerContext</code> has been initialized, the controls in the 
        JUnit test class are declaratively instantiated via the <code>ClientInitializer</code> that was generated for the 
        test case.  
        </p>
        <note>
        In order to use a <code>ClientInitializer</code>, the JUnit test cases must have been processed with the 
        Controls annotation processor via the <code>&lt;build-controls></code> Ant macro.  
        </note>
        <p>
        In cases where a test needs to provide a custom implementation of a Controls container, a new container
        implementation will be created by overriding the
        <a href="apidocs/javadoc/org/apache/beehive/controls/test/junit/ControlTestCase.html#initializeControlContainerContext()">
        initializeControlContainerContext()</a> method.
        </p>
        <p>
        In cases where a test needs to override the base <code>setUp</code> and <code>tearDown</code> JUnit lifecycle
        methods, the test author should remember to call <code>super.setUp()</code> and <code>super.tearDown()</code>
        from the overridden methods.
        </p>
    </section>
    <section id="control-instantiation">
        <title>Control Instantiation</title>
        <p>
        Controls declared with the <code>@Control</code> annotation will be declaratively instantiated by the 
        JUnit container.  These references will be valid for the duration of the JUnit test.
        </p>
    </section>
    <section id="junit-other-baseclass">
        <title>Using another Base Class</title>
        <p>
        In cases where tests are unable to extend the <code>ControlTestCase</code> base class, the Control 
        container and its lifecycle can be implemented using utilities available in the class
        <a href="apidocs/javadoc/org/apache/beehive/controls/test/junit/util/ControlContainerContextManager.html">
        ControlContainerContextManager</a>.  This class provides methods to begin and end a Context, to 
        instantiate controls, and to get the Context object itself.  To implement a <code>ControlContainerContext</code>
        for a single test case, the following code can be added to a test case method:
        </p>
        <source>
public void testFoo() {
    ControlContainerContext ccc = new ControlTestContainerContext();
    ControlContainerContextManager cccManager = ControlContainerContextManagerFactory.getInstance(ccc);
    cccManager.beginContext();
    cccManager.instantiateControls(this);

   ... test code ...
 
   cccManager.endContext();
}
        </source>
        <p>
        The same <code>ControlContainerContext</code> methods could be added to the JUnit test lifecycle methods
        <code>setUp()</code> and <code>tearDown()</code>.
        </p>
    </section>
    <section id="junit-exec">
        <title>Running the JUnit Tests</title>
        <p>
        The JUnit tests for a Control can be executed in a variety of ways including via Ant or from and IDE
        like IntelliJ or Eclipse.  Ant can run these JUnit tests in the usual means by executing them directly
        or by using the optional Ant tasks to support running and reporting results for JUnit tests.  
        </p>
        <p>
        To run Controls JUnit tests from an IDE, the command line build to code generate the Controls support
        classes often needs to be run so that the Control support classes are available in classpath.  Once
        these classes have been generated, an IDE's JUnit integration should successfully.  While this is 
        inconvenient, as support for annotations and APT improves in IDEs, this process should become easier.
        </p>
    </section>
    </body>
</document>