X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsupport%2Fpersistence%2Fpackage-info.java;h=d38be5796fed215c5341d165ce549af23a5d4bbd;hb=28a9820d1b2fe0dbf9a05aed5a84b79f96cde743;hp=1bd7050cfd86aa7a417abf0b9efb103c6e705689;hpb=2207a1e695ce23e79678c232cff2ceb84ebaa801;p=utils diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java index 1bd7050c..d38be579 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java @@ -1,23 +1,214 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** - * This package provide a number of utilities for database testing and in particular with - * JPA. + *

+ * This package provides test library for database testing in general and JPA testing + * specifically. As part of this it provides a means to transparently start an inmemory + * database from a junit test or connect to an external database. Also, given a persistence + * unit it is easy to start testing it in a junit test with only a few lines of code. + *

* - * The following utilities are available: + *

+ * The main use cases are explained below: + *

* + * + *

+ * See the design overview for a an overview of the design. + *

+ * + * + *

Basic database testing, transparently connecting to a database

+ *
+ * Starting the database: + *
+ *      Database db = DatabaseBuilder.getDatabase();
+ *      DataSource dataSource = db.start();
+ * 
+ * If nothing is specified in the user's environment, an inmemory database is started (derby). + * Using the datasource is just standard JDBC now. + * Stopping the database + *
+ *      db.stop();
+ * 
+ * + * + *

Connecting to an external database

+ *
+ * + * Connecting to an external database can be done by requiring the 'external' capability on + * the database provider. + *
+ *      Database db = DatabaseBuilder.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); 
+ * 
+ * This also requires a number of environment variables or system properties to be set, + * see {@link ExternalDatabase}. + * + * + * + *

Executing code within a JDBC transaction

+ *
+ *

+ * To execute code withing a JDBC transaction, use the {@link DatabaseUtils} and + * use the {@link DatabaseUtils#executeInTransaction(org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork)} + * method. + *

+ *
+ *       DatabaseUtils dbutils = new DatabaseUtils(dataSource);
+ *       boolean result = dbutils.executeInTransaction(
+ *           new JdbcUnitOfWork<Boolean>() {
+ *               @Override
+ *               public Boolean execute(Connection aConnection) throws Exception {
+ *                   ResultSet res = jpaTester.getDbUtils().executeQuery(
+ *                       aConnection, GROUP_QUERY, aGroup);
+ *                   return res.next();
+ *               }
+ *           });
+ * 
+ * {@link DatabaseUtils} also provides various other utility methods to work with JDBC queries. + * + * + *

Using DB Unit in your tests

+ *
+ * + *

To work with DBUnit, {@link DatabaseUtils#createDbTester(org.dbunit.dataset.filter.ITableFilterSimple)} + * must be used passing it in the tables to use in the form of a {@link org.dbunit.dataset.filter.ITableFilterSimple} + * object.

+ * + *
+ *      IDatabaseTester dbtester = dbutils.createDbTester(new ITableFilterSimple() {
+ *          public boolean accept(String aTableName) throws DataSetException {
+ *              return aTableName.startsWith("XYZ_");
+ *          }
+ *      });
+ * 
+ * + *

The reason for using a DatabaseUtils instead of DBUnit directly is that + * DatabseUtils will keep track of connections and close them when DatabaseUtils + * is closed

+ * + * + *

Basic JPA testing

+ *
+ *

+ * First step is to create a {@link PersistenceUnitDescription} that matches the persistence unit you + * want to test. + *

+ *

Second step is to make sure that all entities are listed explicitly in your + *

persistence.xml
. Currently, class path scanning appears to fail when + * run from junit. + * Specifying all entities explicitly is not necessarily a bad thing as it is also more efficient. + *

+ * + *

+ * Now create a JpaTester in your test code: + *

+ *
+ *      @Before
+ *      public void setUp() throws Exception {
+ * 
+ *          // First we create the JpaTester by telling us which persistence unit we
+ *          // are going to test
+ *          jpaTester = new JpaTester(new MyPersistenceUnit());
+ *          jpaTester.start();     
+ *      }
+ * 
+ * + *

+ * Then in test code execute some JPA code within a unit of work: + *

+ *
+ *      jpaTester.getJpaBuilder().execute(new JpaUnitOfWork() {
+ *          public Void execute(EntityManager aEm) {
+ *              MyEntity entity = new MyEntity("a", "b");
+ *              aEm.persist(entity);
+ *              return null;
+ *          }
+ *      });
+ * 
+ * + * + *

JPA testing combined with JDBC and DBUnit

+ *
+ *

The JPATester provides access to all required object. It is usually convenient to + * get them directly from the JPATester after initializing it: + *

+ *      builder = jpaTester.getJpaBuilder();
+ *      dbtester = jpaTester.getDbUtils().createDbTester(new MyTables());
+ *      dbutils = jpaTester.getDbUtils();
+ * 
+ * + * + *

Testing a service that requires a transaction

+ *
+ * + *

Using {@link TransactionProxyFactory} it is possible to create a proxy for a given + * service interface to provide the semantics of 'requires new' transaction semantics. + *

+ *      TransactionProxyFactory factory = new TransactionProxyFactory(
+ *           jpaTester.getJpaBuilder(), Service.class);
+ *      Service service = new ServiceImpl(factory.getTransactionScopedEntityManager()); 
+ *      Service proxy = factory.getProxy(service);
+ *      proxy.execute(...);
+ * 
+ * + *

+ * In the above example, the Service POJO requires an {@link EntityManager} in its + * constructor and it is passed a transaction scoped entitymanager from the factory. This entitymanager + * is in fact a so-called contextual reference. + * Next, the proxy is obtained from the factory. Invoking any method on it will make sure a new + * transaction is started and a new entity manager is created for the scope of that transaction. + *

+ * + * + *

design overview

+ *
+ * + *

Database transaparency

+ * + *

Testing using JDBC and DBUnit

+ * + *

JPA tester overview

+ * + * + * */ package org.wamblee.support.persistence; + +import static org.mockito.Mockito.*; + +import javax.persistence.EntityManager; + +import org.junit.Before; +import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; +import org.wamblee.support.persistence.TransactionProxyFactoryTestBase.Service; + +