View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  package org.dbunit.database;
22  
23  import static org.assertj.core.api.Assertions.assertThat;
24  
25  import java.io.PrintWriter;
26  import java.sql.Connection;
27  import java.sql.DriverManager;
28  import java.sql.SQLException;
29  import java.sql.SQLFeatureNotSupportedException;
30  import java.util.logging.Logger;
31  
32  import javax.sql.DataSource;
33  
34  import org.dbunit.AbstractDatabaseIT;
35  import org.dbunit.DatabaseProfile;
36  import org.dbunit.dataset.IDataSet;
37  import org.junit.jupiter.api.Test;
38  
39  /**
40   * Integration tests for {@link DatabaseDataSourceConnection}.
41   *
42   * <p>These tests verify construction variants, connection caching, schema
43   * storage, close behaviour, and the ability to perform real database operations
44   * through the DataSource-backed connection.
45   *
46   * @since 3.2.0
47   */
48  class DatabaseDataSourceConnectionIT extends AbstractDatabaseIT
49  {
50      /**
51       * Minimal {@link DataSource} backed by {@link DriverManager}.  Opens a new
52       * physical connection per {@link #getConnection()} call so that each test
53       * can observe independently-managed connections.
54       */
55      private static class ProfileDataSource implements DataSource
56      {
57          private final String url;
58          private final String user;
59          private final String password;
60  
61          ProfileDataSource(final String url, final String user,
62                  final String password)
63          {
64              this.url = url;
65              this.user = user;
66              this.password = password;
67          }
68  
69          @Override
70          public Connection getConnection() throws SQLException
71          {
72              return DriverManager.getConnection(url, user, password);
73          }
74  
75          @Override
76          public Connection getConnection(final String u, final String p)
77                  throws SQLException
78          {
79              return DriverManager.getConnection(url, u, p);
80          }
81  
82          @Override
83          public PrintWriter getLogWriter()
84          {
85              return null;
86          }
87  
88          @Override
89          public void setLogWriter(final PrintWriter out)
90          {
91          }
92  
93          @Override
94          public void setLoginTimeout(final int seconds)
95          {
96          }
97  
98          @Override
99          public int getLoginTimeout()
100         {
101             return 0;
102         }
103 
104         @Override
105         public Logger getParentLogger() throws SQLFeatureNotSupportedException
106         {
107             throw new SQLFeatureNotSupportedException();
108         }
109 
110         @Override
111         public <T> T unwrap(final Class<T> iface) throws SQLException
112         {
113             throw new SQLException("Not a wrapper.");
114         }
115 
116         @Override
117         public boolean isWrapperFor(final Class<?> iface)
118         {
119             return false;
120         }
121     }
122 
123     private DataSource buildDataSource() throws Exception
124     {
125         final DatabaseProfile profile = getEnvironment().getProfile();
126         Class.forName(profile.getDriverClass());
127         return new ProfileDataSource(profile.getConnectionUrl(),
128                 profile.getUser(), profile.getPassword());
129     }
130 
131     private String profileSchema() throws Exception
132     {
133         return getEnvironment().getProfile().getSchema();
134     }
135 
136     private String profileUser() throws Exception
137     {
138         return getEnvironment().getProfile().getUser();
139     }
140 
141     private String profilePassword() throws Exception
142     {
143         return getEnvironment().getProfile().getPassword();
144     }
145 
146     // -------------------------------------------------------------------------
147     // getConnection — lazy open and caching
148     // -------------------------------------------------------------------------
149 
150     @Test
151     void testGetConnection_withDataSourceOnly_returnsOpenConnection()
152             throws Exception
153     {
154         final DatabaseDataSourceConnection conn =
155                 new DatabaseDataSourceConnection(buildDataSource());
156         try
157         {
158             final Connection jdbc = conn.getConnection();
159             assertThat(jdbc).as("connection returned.").isNotNull();
160             assertThat(jdbc.isClosed()).as("connection is open.").isFalse();
161         } finally
162         {
163             conn.close();
164         }
165     }
166 
167     @Test
168     void testGetConnection_calledTwice_returnsSameInstance() throws Exception
169     {
170         final DatabaseDataSourceConnection conn =
171                 new DatabaseDataSourceConnection(buildDataSource());
172         try
173         {
174             final Connection first = conn.getConnection();
175             final Connection second = conn.getConnection();
176             assertThat(second).as("same instance returned on second call.")
177                     .isSameAs(first);
178         } finally
179         {
180             conn.close();
181         }
182     }
183 
184     // -------------------------------------------------------------------------
185     // getSchema
186     // -------------------------------------------------------------------------
187 
188     @Test
189     void testGetSchema_withNoSchemaConstructor_returnsNull() throws Exception
190     {
191         final DatabaseDataSourceConnection conn =
192                 new DatabaseDataSourceConnection(buildDataSource());
193         try
194         {
195             assertThat(conn.getSchema()).as("no-schema constructor gives null.").isNull();
196         } finally
197         {
198             conn.close();
199         }
200     }
201 
202     @Test
203     void testGetSchema_withExplicitSchema_returnsSchema() throws Exception
204     {
205         final String schema = profileSchema();
206         final DatabaseDataSourceConnection conn =
207                 new DatabaseDataSourceConnection(buildDataSource(), schema);
208         try
209         {
210             assertThat(conn.getSchema()).as("schema stored correctly.").isEqualTo(schema);
211         } finally
212         {
213             conn.close();
214         }
215     }
216 
217     // -------------------------------------------------------------------------
218     // close
219     // -------------------------------------------------------------------------
220 
221     @Test
222     void testClose_withOpenConnection_closesUnderlyingJdbcConnection()
223             throws Exception
224     {
225         final DatabaseDataSourceConnection conn =
226                 new DatabaseDataSourceConnection(buildDataSource());
227         final Connection jdbc = conn.getConnection();
228         assertThat(jdbc.isClosed()).as("open before close.").isFalse();
229 
230         conn.close();
231 
232         assertThat(jdbc.isClosed()).as("closed after close().").isTrue();
233     }
234 
235     @Test
236     void testClose_withoutPriorGetConnection_doesNotThrow() throws Exception
237     {
238         final DatabaseDataSourceConnection conn =
239                 new DatabaseDataSourceConnection(buildDataSource());
240         // close() before any getConnection() call must be a safe no-op
241         conn.close();
242     }
243 
244     @Test
245     void testClose_calledTwice_doesNotThrow() throws Exception
246     {
247         final DatabaseDataSourceConnection conn =
248                 new DatabaseDataSourceConnection(buildDataSource());
249         conn.getConnection();
250         conn.close();
251         conn.close();
252     }
253 
254     @Test
255     void testGetConnection_afterClose_returnsNewOpenConnection() throws Exception
256     {
257         final DatabaseDataSourceConnection conn =
258                 new DatabaseDataSourceConnection(buildDataSource());
259         try
260         {
261             final Connection first = conn.getConnection();
262             conn.close();
263             assertThat(first.isClosed()).as("first connection closed.").isTrue();
264 
265             final Connection second = conn.getConnection();
266             assertThat(second).as("new connection obtained after close.").isNotNull();
267             assertThat(second.isClosed()).as("new connection is open.").isFalse();
268             assertThat(second).as("different instance from closed connection.")
269                     .isNotSameAs(first);
270         } finally
271         {
272             conn.close();
273         }
274     }
275 
276     // -------------------------------------------------------------------------
277     // Constructor with user / password
278     // -------------------------------------------------------------------------
279 
280     @Test
281     void testGetConnection_withUserAndPassword_returnsOpenConnection()
282             throws Exception
283     {
284         final DatabaseDataSourceConnection conn = new DatabaseDataSourceConnection(
285                 buildDataSource(), profileUser(), profilePassword());
286         try
287         {
288             final Connection jdbc = conn.getConnection();
289             assertThat(jdbc).as("connection via user/password.").isNotNull();
290             assertThat(jdbc.isClosed()).as("connection is open.").isFalse();
291         } finally
292         {
293             conn.close();
294         }
295     }
296 
297     @Test
298     void testGetSchema_withUserPasswordConstructorAndNoSchema_returnsNull()
299             throws Exception
300     {
301         final DatabaseDataSourceConnection conn = new DatabaseDataSourceConnection(
302                 buildDataSource(), profileUser(), profilePassword());
303         try
304         {
305             assertThat(conn.getSchema())
306                     .as("user/password constructor has no schema.").isNull();
307         } finally
308         {
309             conn.close();
310         }
311     }
312 
313     // -------------------------------------------------------------------------
314     // Full constructor (schema + user + password)
315     // -------------------------------------------------------------------------
316 
317     @Test
318     void testGetSchema_withSchemaAndUserPasswordConstructor_returnsSchema()
319             throws Exception
320     {
321         final String schema = profileSchema();
322         final DatabaseDataSourceConnection conn = new DatabaseDataSourceConnection(
323                 buildDataSource(), schema, profileUser(), profilePassword());
324         try
325         {
326             assertThat(conn.getSchema()).as("schema from full constructor.").isEqualTo(schema);
327         } finally
328         {
329             conn.close();
330         }
331     }
332 
333     // -------------------------------------------------------------------------
334     // Integration: real database operations
335     // -------------------------------------------------------------------------
336 
337     @Test
338     void testCreateDataSet_withDataSourceConnection_returnsDataSetContainingTestTable()
339             throws Exception
340     {
341         final String schema = profileSchema();
342         final DatabaseDataSourceConnection conn =
343                 new DatabaseDataSourceConnection(buildDataSource(), schema);
344         try
345         {
346             final IDataSet dataSet = conn.createDataSet();
347             assertThat(dataSet).as("dataset created.").isNotNull();
348             assertThat(dataSet.getTableNames())
349                     .as("dataset contains at least one table.").isNotEmpty();
350         } finally
351         {
352             conn.close();
353         }
354     }
355 
356     @Test
357     void testGetRowCount_withDataSourceConnection_returnsCorrectRowCount()
358             throws Exception
359     {
360         final String schema = profileSchema();
361         final DatabaseDataSourceConnection conn =
362                 new DatabaseDataSourceConnection(buildDataSource(), schema);
363         try
364         {
365             assertThat(conn.getRowCount("TEST_TABLE"))
366                     .as("TEST_TABLE row count from DataSource connection.")
367                     .isEqualTo(6);
368         } finally
369         {
370             conn.close();
371         }
372     }
373 
374     @Test
375     void testCreateQueryTable_withDataSourceConnection_returnsTableWithRows()
376             throws Exception
377     {
378         final String schema = profileSchema();
379         final DatabaseDataSourceConnection conn =
380                 new DatabaseDataSourceConnection(buildDataSource(), schema);
381         try
382         {
383             final String sql = "SELECT * FROM TEST_TABLE";
384             final org.dbunit.dataset.ITable table =
385                     conn.createQueryTable("TEST_TABLE", sql);
386             assertThat(table).as("query table returned.").isNotNull();
387             assertThat(table.getRowCount()).as("rows returned by query.").isEqualTo(6);
388         } finally
389         {
390             conn.close();
391         }
392     }
393 }