ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

J2EE Without the Application Server
Pages: 1, 2, 3, 4, 5, 6, 7

Step 3: Testing the BankDAO

Let's test our code, then. (Extreme programmers would write the tests first, but for the sake of clarity, we delayed this step until now.) A simple unit test can be found below. This test can be run from within your standard IDE; no application server is involved. The unit test is designed as a mini-application on its own: it uses Spring to retrieve a configured Bank object to test (this is done in the setUp method). Note that the test uses explicit transaction demarcation: a transaction is started before each test and rollback is forced at the end of each test. This is a handy way to minimize the effects of testing on the database data.



package jdbc;
import com.atomikos.icatch.jta.UserTransactionImp;
import junit.framework.TestCase;
import java.io.FileInputStream;
import java.io.InputStream;
import org.springframework.beans.factory.xml.XmlBeanFactory;

public class BankTest extends TestCase
{

    private UserTransactionImp utx;

    private Bank bank;

    public BankTest ( String name )
    {
        super ( name );
        utx = new UserTransactionImp();
        

    }

    protected void setUp()
        throws Exception
    {
        //start a new transaction
        //so we can rollback the
        //effects of each test
        //in teardown!
        utx.begin();
        
        //open bean XML file
        InputStream is =
            new FileInputStream("config.xml");

        //the factory is Spring's entry point
        //for retrieving the configured
        //objects from the XML file

        XmlBeanFactory factory =
            new XmlBeanFactory(is);

        bank = ( Bank ) factory.getBean ( "bank" );
        bank.checkTables();
    }

    protected void tearDown()
        throws Exception
    {
        //rollback all DBMS effects
        //of testing
        utx.rollback();
    }

    public void testBank()
    throws Exception
    {
        int accNo = 10;
        long initialBalance = bank.getBalance ( accNo );
        bank.withdraw ( accNo , 100 );
        long newBalance = bank.getBalance ( accNo );
        if ( ( initialBalance - newBalance ) != 100 )
            fail ( "Wrong balance after withdraw: " +
                   newBalance );
    }
    
}

We will need JTA transactions to make sure that both the JMS and the JDBC are performed atomically. In general, you should consider JTA/XA whenever two or more connectors are needed, such as JMS and JDBC in our case. Spring doesn't offer JTA transactions by itself; it needs a JTA implementation and normally delegates to an application server to do that. However, we are using an embeddable JTA implementation that works on any J2SE platform.

The resulting architecture is show below in Figure 3. The white boxes represent our application code.

Architecture for the test
Figure 3. Architecture for the test

As you can see, the following happens when we run our test:

  1. The BankTest starts a new transaction.
  2. The test then retrieves the object named bank from the Spring runtime. This step triggers Spring's creation and initialization process.
  3. The test calls the bank's method(s).
  4. The bank invokes the object named datasource, which it has received from Spring via its setDataSource method.
  5. The datasource is JTA-enabled and interacts with the JTA implementation to register with the current transaction.
  6. JDBC statements interact with the accounts database.
  7. When the method returns, the test calls rollback for the transaction.
  8. JTA remembers the datasource and instructs it to roll back.

Pages: 1, 2, 3, 4, 5, 6, 7

Next Pagearrow