View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2026, 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;
22  
23  import static org.assertj.core.api.Assertions.assertThat;
24  import static org.assertj.core.api.Assertions.assertThatThrownBy;
25  
26  import java.util.concurrent.atomic.AtomicInteger;
27  
28  import javax.sql.DataSource;
29  
30  import org.dbunit.database.CachingConnectionProvider;
31  import org.dbunit.database.DatabaseConfig;
32  import org.dbunit.database.IDatabaseConnection;
33  import org.h2.jdbcx.JdbcDataSource;
34  import org.junit.jupiter.api.AfterEach;
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * Integration tests for {@link DataSourceDatabaseTester}, run against a real
39   * H2 in-memory {@link DataSource}, focused on its opt-in
40   * {@link CachingConnectionProvider} integration.
41   *
42   * @since 3.4.0
43   */
44  class DataSourceDatabaseTesterIT
45  {
46      private static final AtomicInteger DB_COUNTER = new AtomicInteger();
47  
48      private IDatabaseConnection openedConnection;
49  
50      @AfterEach
51      void closeOpenedConnection() throws Exception
52      {
53          if (openedConnection != null)
54          {
55              openedConnection.close();
56          }
57      }
58  
59      @Test
60      void testGetConnection_withoutProvider_returnsDifferentInstanceOnEachCall() throws Exception
61      {
62          final DataSourceDatabaseTester tester = new DataSourceDatabaseTester(newDataSource());
63  
64          final IDatabaseConnection first = tester.getConnection();
65          final IDatabaseConnection second = tester.getConnection();
66  
67          assertThat(second)
68                  .as("Without a CachingConnectionProvider, every call must create a fresh "
69                          + "connection, matching pre-existing behavior.")
70                  .isNotSameAs(first);
71          first.close();
72          second.close();
73      }
74  
75      @Test
76      void testGetConnection_withProvider_returnsSameInstanceOnEachCall() throws Exception
77      {
78          final CachingConnectionProvider provider = new CachingConnectionProvider();
79          final DataSourceDatabaseTester tester =
80                  new DataSourceDatabaseTester(newDataSource(), null, provider);
81  
82          final IDatabaseConnection first = tester.getConnection();
83          final IDatabaseConnection second = tester.getConnection();
84  
85          openedConnection = second;
86          assertThat(second)
87                  .as("With a CachingConnectionProvider, calls must reuse the cached connection.")
88                  .isSameAs(first);
89      }
90  
91      @Test
92      void testGetConnection_withProvider_afterUnderlyingConnectionDies_returnsNewWorkingConnection()
93              throws Exception
94      {
95          final CachingConnectionProvider provider = new CachingConnectionProvider();
96          final DataSourceDatabaseTester tester =
97                  new DataSourceDatabaseTester(newDataSource(), null, provider);
98  
99          final IDatabaseConnection first = tester.getConnection();
100         first.getConnection().close();
101 
102         final IDatabaseConnection second = tester.getConnection();
103 
104         openedConnection = second;
105         assertThat(second).as("A dead cached connection must be transparently replaced.")
106                 .isNotSameAs(first);
107         assertThat(second.getConnection().createStatement().execute("SELECT 1"))
108                 .as("The replacement connection must be a real, working JDBC connection.")
109                 .isTrue();
110     }
111 
112     @Test
113     void testConstructor_withNullDataSourceAndProvider_throwsNullPointerException()
114     {
115         assertThatThrownBy(
116                 () -> new DataSourceDatabaseTester(null, null, new CachingConnectionProvider()))
117                         .as("The 3-arg constructor must reject a null DataSource just like the "
118                                 + "pre-existing constructors do.")
119                         .isInstanceOf(NullPointerException.class);
120     }
121 
122     @Test
123     void testGetConnection_withDatabaseConfig_appliesConfiguredPropertiesToConnection()
124             throws Exception
125     {
126         final DatabaseConfig databaseConfig = new DatabaseConfig();
127         databaseConfig.setProperty(DatabaseConfig.PROPERTY_BATCH_SIZE, 500);
128         final DataSourceDatabaseTester tester =
129                 new DataSourceDatabaseTester(newDataSource(), null, null, databaseConfig);
130 
131         final IDatabaseConnection connection = tester.getConnection();
132 
133         openedConnection = connection;
134         assertThat(connection.getConfig().getProperty(DatabaseConfig.PROPERTY_BATCH_SIZE))
135                 .as("The DatabaseConfig supplied to the constructor must be applied to every "
136                         + "connection this tester creates.")
137                 .isEqualTo(500);
138     }
139 
140     @Test
141     void testGetConnection_withDatabaseConfigAndProvider_appliesConfiguredPropertiesToCachedConnection()
142             throws Exception
143     {
144         final DatabaseConfig databaseConfig = new DatabaseConfig();
145         databaseConfig.setProperty(DatabaseConfig.PROPERTY_BATCH_SIZE, 500);
146         final CachingConnectionProvider provider = new CachingConnectionProvider();
147         final DataSourceDatabaseTester tester =
148                 new DataSourceDatabaseTester(newDataSource(), null, provider, databaseConfig);
149 
150         final IDatabaseConnection connection = tester.getConnection();
151 
152         openedConnection = connection;
153         assertThat(connection.getConfig().getProperty(DatabaseConfig.PROPERTY_BATCH_SIZE))
154                 .as("The DatabaseConfig supplied to the constructor must be applied even when a "
155                         + "CachingConnectionProvider is used.")
156                 .isEqualTo(500);
157     }
158 
159     @Test
160     void testConstructor_withNullDataSourceAndProviderAndConfig_throwsNullPointerException()
161     {
162         assertThatThrownBy(() -> new DataSourceDatabaseTester(null, null,
163                 new CachingConnectionProvider(), new DatabaseConfig()))
164                         .as("The 4-arg constructor must reject a null DataSource just like the "
165                                 + "pre-existing constructors do.")
166                         .isInstanceOf(NullPointerException.class);
167     }
168 
169     private static DataSource newDataSource()
170     {
171         final JdbcDataSource dataSource = new JdbcDataSource();
172         dataSource.setUrl(
173                 "jdbc:h2:mem:datasourcetester_" + DB_COUNTER.incrementAndGet() + ";DB_CLOSE_DELAY=-1");
174         return dataSource;
175     }
176 }