See: Description
Interface | Description |
---|---|
Database |
Represents a database.
|
DatabaseProvider |
Database provider.
|
DatabaseUtils.JdbcUnitOfWork<T> |
Represents a unit of work (transaction).
|
DatabaseUtils.TableSet |
Represents a set of tables.
|
DatabaseUtils.TableSetOperation |
Operation to be executed on a set of tables for each table individually.
|
JpaBuilder.JpaUnitOfWork<T> |
Callback interface to execute some JPA code within a transaction with the
entitymanager to use provided as input.
|
JpaCustomizer |
JPA customizer is used to customize properties for a given JPA
implementation.
|
TransactionResultCallback |
Callback to notify the test of the result of the transaction.
|
Class | Description |
---|---|
AbstractDatabase |
Abstract database class providing the creation of the datasource, preventing
duplicate starts of the same database, and checking for connection leaks when
the database is stopped.
|
AbstractDatabaseProvider |
Base class for database providers.
|
CompositeJpaCustomizer |
Composite JPA customizer that applies the customizations from several JPA
customizers.
|
CompositeJpaTables |
Composite JPA tables.
|
DatabaseBuilder |
DatabaseBuilder is used from unit test to obtain a reference to a database
from unit test.
|
DatabaseDescription |
Description of a specific database.
|
DatabaseStarter |
This class is used for starting the database as a main program.
|
DatabaseUtils |
Database utilities is a simple support class for common tasks in working with
databases.
|
DerbyDatabase |
Derby database setup.
|
DerbyDatabaseProvider |
Derby database provider.
|
ExternalDatabase |
Database that encapsulates connection to an external database.
|
ExternalDatabaseProvider |
Database provider for an external database.
|
JpaBuilder |
Utility for building an appropriately configured EntityManagerFactory.
|
JpaCustomizerBuilder |
JPA customizer builder implements the
ServiceLoader based mechanism
for looking up JPA customizers. |
JpaTester |
This class is the entry point for JPA tests.
|
LoggingTransactionResultCallback |
Logging the result of a transaction.
|
PersistenceUnitDescription |
Describes a persistence unit.
|
RequireTransactionStatus |
Specific transaction result callback to require a specific transaction
result.
|
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 main use cases are explained below:
UserTransaction
See also the design overview.
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.
After a test it is good practice to stop the database:
db.stop();
Database db = DatabaseBuilder.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL);This also requires a number of environment variables or system properties to be set, see
ExternalDatabase
.
However, the most convenient way to set the capabilities is usually to set a system property or environment
variable see the javadocs of DatabaseBuilder
. and
specifically DatabaseBuilder.DB_CAPABILITIES_PROP
To execute code withing a JDBC transaction, use the DatabaseUtils
and
use the 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(); } });
DatabaseUtils
also provides various other utility methods to work with JDBC queries.
To work with DBUnit,
DatabaseUtils#createDbTester(org.dbunit.dataset.filter.ITableFilterSimple)
must be used passing it in the tables to use in the form of a 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
First step is to create a 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; } });
Note that in addition to this method it is also possible to directly control transactions
through JpaBuilder#begin()
, JpaBuilder#commit(javax.persistence.EntityManager)
,
and JpaBuilder#rollback(javax.persistence.EntityManager)
.
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(); dbutils = jpaTester.getDbUtils(); dbtester = dbutils.createDbTester(new MyTables());
Using TransactionProxyFactory
it is possible to create a proxy for a given
service interface to provide the semantics of 'requires new' transaction semantics.
TransactionProxyFactoryfactory = 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 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.
UserTransaction
It is also possible to manage JPA transaction through a UserTransaction
.
This is mostly useful if you are test software that uses UserTransaction
for
managing transactions, or if you want to manage multiple transactional resources.
See the explanation at SimpleTransactionManager
for more details.
DatabaseProvider
uses java.util.ServiceLoader
to find all implementations
of DatabaseProvider
on the classpath. It then asks the database providers whether
they support the required capabilities (by default inmemory), and the first provider that
supports the capabilities is used to create the database.
Note that the Database
interface is not intended to always create a database.
It will do so for DerbyDatabase
(inmemory), but with ExternalDatabase
it simply connects to an external database based on system properties or environment
variables.
JPATester
is responsible for:
DatabaseBuilder
.
org.wamblee.support.jndi.StubInitialContextFactory
.
JPABuilder
that will do the JPA heavy lifting.
DatabaseUtils
for JDBC and DBUnit testing.
Copyright © 2022. All rights reserved.