(no commit message)
[utils] / test / enterprise / src / main / java / org / wamblee / support / persistence / package-info.java
1 /*
2  * Copyright 2005-2010 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */ 
16 /**
17  * <p>
18  * This package provides test library for database testing in general and JPA testing
19  * specifically. As part of this it provides a means to transparently start an inmemory 
20  * database from a junit test or connect to an external database. Also, given a persistence 
21  * unit it is easy to start testing it in a junit test with only a few lines of code.
22  * </p> 
23  * 
24  * <p>
25  * The main use cases are explained below:
26  * </p> 
27  * <ul>
28  *   <li> <a href="#db-basic">Basic database testing, transparently connecting to a database</a>  
29  *   </li>
30  *   <li> <a href="#db-basic-external">Connecting to an external database</a>
31  *   </li>
32  *   <li> <a href="#db-utils">Executing code within a JDBC transaction</a>
33  *   </li>
34  *   <li> <a href="#db-unit">Using DB Unit in your tests</a>
35  *   </li>
36  *   <li> <a href="#db-jpa-basic">Basic JPA testing</a> 
37  *   </li>
38  *   <li> <a href="#db-jpa-plus-jdbc">JPA testing combined with JDBC and DBUnit</a>
39  *   </li>
40  *   <li> <a href="#db-jpa-services">Testing a service that requires a transaction</a>
41  *   </li>
42  * </ul>
43  * 
44  * <p>
45  *   See the <a href="#design-overview">design overview</a> for a an overview of the design.  
46  * </p>
47  * 
48  * <a name="db-basic">
49  *   <h2>Basic database testing, transparently connecting to a database</h2>
50  * </a>
51  * Starting the database: 
52  * <pre>
53  *      Database db = DatabaseBuilder.getDatabase();
54  *      DataSource dataSource = db.start();
55  * </pre>
56  * If nothing is specified in the user's environment, an inmemory database is started (derby).
57  * Using the datasource is just standard JDBC now. 
58  * Stopping the database
59  * <pre>
60  *      db.stop();
61  * </pre>
62  * 
63  * <a name="db-basic-external">
64  *   <h2>Connecting to an external database</h2>
65  * </a>
66  * 
67  * Connecting to an external database can be done by requiring the 'external' capability on 
68  * the database provider. 
69  * <pre>
70  *      Database db = DatabaseBuilder.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); 
71  * </pre>
72  * This also requires a number of environment variables or system properties to be set, 
73  * see {@link ExternalDatabase}. 
74  * 
75  * 
76  * <a name="db-utils">
77  *   <h2>Executing code within a JDBC transaction</h2>
78  * </a>
79  * <p>
80  *   To execute code withing a JDBC transaction, use the {@link DatabaseUtils} and 
81  *   use the {@link DatabaseUtils#executeInTransaction(org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork)}
82  *   method. 
83  * </p>
84  * <pre>
85  *       DatabaseUtils dbutils = new DatabaseUtils(dataSource);
86  *       boolean result = dbutils.executeInTransaction(
87  *           new JdbcUnitOfWork&lt;Boolean&gt;() {
88  *               &#064;Override
89  *               public Boolean execute(Connection aConnection) throws Exception {
90  *                   ResultSet res = jpaTester.getDbUtils().executeQuery(
91  *                       aConnection, GROUP_QUERY, aGroup);
92  *                   return res.next();
93  *               }
94  *           });
95  * </pre>
96  * {@link DatabaseUtils} also provides various other utility methods to work with JDBC queries. 
97  * 
98  * <a name="db-unit">
99  *   <h2>Using DB Unit in your tests</h2>
100  * </a>
101  * 
102  * <p>To work with <a href="http://dbunit.org">DBUnit</a>, {@link DatabaseUtils#createDbTester(org.dbunit.dataset.filter.ITableFilterSimple)}
103  * must be used passing it in the tables to use in the form of a {@link org.dbunit.dataset.filter.ITableFilterSimple}
104  * object. </p>
105  * 
106  * <pre>
107  *      IDatabaseTester dbtester = dbutils.createDbTester(new ITableFilterSimple() {
108  *          public boolean accept(String aTableName) throws DataSetException {
109  *              return aTableName.startsWith("XYZ_");
110  *          }
111  *      });
112  * </pre>
113  * 
114  * <p>The reason for using a <code>DatabaseUtils</code> instead of DBUnit directly is that 
115  * <code>DatabseUtils</code> will keep track of connections and close them when <code>DatabaseUtils</code>
116  * is closed</p>
117  * 
118  * <a name="db-jpa-basic">
119  *   <h2>Basic JPA testing</h2>
120  * </a>
121  * <p>
122  *    First step is to create a {@link PersistenceUnitDescription} that matches the persistence unit you
123  *    want to test. 
124  * </p>
125  * <p>Second step is to make sure that all entities are listed explicitly in your
126  *    <pre>persistence.xml</pre>. Currently, class path scanning appears to fail when
127  *    run from junit. 
128  *    Specifying all entities explicitly is not necessarily a bad thing as it is also more efficient. 
129  * </p>
130  * 
131  * <p>
132  *    Now create a <code>JpaTester</code> in your test code: 
133  * </p>
134  * <pre>
135  *      &#064;Before
136  *      public void setUp() throws Exception {
137  * 
138  *          // First we create the JpaTester by telling us which persistence unit we
139  *          // are going to test
140  *          jpaTester = new JpaTester(new MyPersistenceUnit());
141  *          jpaTester.start();     
142  *      }
143  * </pre>
144  * 
145  * <p>
146  * Then in test code execute some JPA code within a unit of work: 
147  * </p>
148  * <pre>
149  *      jpaTester.getJpaBuilder().execute(new JpaUnitOfWork<Void>() {
150  *          public Void execute(EntityManager aEm) {
151  *              MyEntity entity = new MyEntity("a", "b");
152  *              aEm.persist(entity);
153  *              return null;
154  *          }
155  *      });
156  * </pre>
157  * 
158  * <a name="db-jpa-plus-jdbc">
159  *   <h2>JPA testing combined with JDBC and DBUnit</h2>
160  * </a>
161  * <p>The <code>JPATester</code> provides access to all required object. It is usually convenient to 
162  * get them directly from the <code>JPATester</code> after initializing it: 
163  * <pre>
164  *      builder = jpaTester.getJpaBuilder();
165  *      dbtester = jpaTester.getDbUtils().createDbTester(new MyTables());
166  *      dbutils = jpaTester.getDbUtils();
167  * </pre>
168  * 
169  * <a name="db-jpa-services">
170  *   <h2>Testing a service that requires a transaction</h2>
171  * </a>
172  * 
173  * <p>Using {@link TransactionProxyFactory} it is possible to create a proxy for a given
174  * service interface to provide the semantics of 'requires new' transaction semantics. 
175  * <pre>
176  *      TransactionProxyFactory<Service> factory = new TransactionProxyFactory<Service>(
177  *           jpaTester.getJpaBuilder(), Service.class);
178  *      Service service = new ServiceImpl(factory.getTransactionScopedEntityManager()); 
179  *      Service proxy = factory.getProxy(service);
180  *      proxy.execute(...);
181  * </pre>
182  * 
183  * <p>
184  * In the above example, the <code>Service</code> POJO requires an {@link EntityManager} in its 
185  * constructor and it is passed a transaction scoped entitymanager from the factory. This entitymanager
186  * is in fact a so-called contextual reference.
187  * Next, the proxy is obtained from the factory. Invoking any method on it will make sure a new 
188  * transaction is started and a new entity manager is created for the scope of that transaction.
189  * </p> 
190  * 
191  * <a name="design-overview">
192  *   <h2>design overview</h2>
193  * </a>
194  * 
195  * <h3>Database transaparency</h3>
196  * 
197  * <h3>Testing using JDBC and DBUnit</h3> 
198  * 
199  * <h3>JPA tester overview</h3>
200  * 
201  * 
202  * 
203  */
204 package org.wamblee.support.persistence;
205
206 import static org.mockito.Mockito.*;
207
208 import javax.persistence.EntityManager;
209
210 import org.junit.Before;
211 import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
212 import org.wamblee.support.persistence.TransactionProxyFactoryTestBase.Service;
213
214