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  
25  import java.util.Properties;
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.IDatabaseConnection;
32  import org.dbunit.database.InMemoryJndiContextFactory;
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 JndiDatabaseTester}, run against a real
39   * {@link javax.naming.InitialContext} (backed by the in-memory
40   * {@link InMemoryJndiContextFactory}) resolving a real H2 in-memory
41   * {@link DataSource}, focused on its opt-in
42   * {@link CachingConnectionProvider} integration.
43   *
44   * @since 3.4.0
45   */
46  class JndiDatabaseTesterIT
47  {
48      private static final AtomicInteger DB_COUNTER = new AtomicInteger();
49  
50      private IDatabaseConnection openedConnection;
51      private String boundName;
52  
53      @AfterEach
54      void closeOpenedConnection() throws Exception
55      {
56          if (openedConnection != null)
57          {
58              openedConnection.close();
59          }
60          if (boundName != null)
61          {
62              InMemoryJndiContextFactory.unbind(boundName);
63          }
64      }
65  
66      @Test
67      void testGetConnection_withoutProvider_returnsDifferentInstanceOnEachCall() throws Exception
68      {
69          final JndiDatabaseTester tester = tester(null);
70  
71          final IDatabaseConnection first = tester.getConnection();
72          final IDatabaseConnection second = tester.getConnection();
73  
74          assertThat(second)
75                  .as("Without a CachingConnectionProvider, every call must create a fresh "
76                          + "connection, matching pre-existing behavior.")
77                  .isNotSameAs(first);
78          first.close();
79          second.close();
80      }
81  
82      @Test
83      void testGetConnection_withProvider_returnsSameInstanceOnEachCall() throws Exception
84      {
85          final JndiDatabaseTester tester = tester(new CachingConnectionProvider());
86  
87          final IDatabaseConnection first = tester.getConnection();
88          final IDatabaseConnection second = tester.getConnection();
89  
90          openedConnection = second;
91          assertThat(second)
92                  .as("With a CachingConnectionProvider, calls must reuse the cached connection.")
93                  .isSameAs(first);
94      }
95  
96      @Test
97      void testGetConnection_withProvider_afterUnderlyingConnectionDies_returnsNewWorkingConnection()
98              throws Exception
99      {
100         final JndiDatabaseTester tester = tester(new CachingConnectionProvider());
101 
102         final IDatabaseConnection first = tester.getConnection();
103         first.getConnection().close();
104 
105         final IDatabaseConnection second = tester.getConnection();
106 
107         openedConnection = second;
108         assertThat(second).as("A dead cached connection must be transparently replaced.")
109                 .isNotSameAs(first);
110         assertThat(second.getConnection().createStatement().execute("SELECT 1"))
111                 .as("The replacement connection must be a real, working JDBC connection.")
112                 .isTrue();
113     }
114 
115     @Test
116     void testGetConnection_withProvider_looksUpJndiOnlyOnceEvenAcrossConnectionReplacement()
117             throws Exception
118     {
119         final JdbcDataSource dataSource = newDataSource();
120         final String lookupName = InMemoryJndiContextFactory.bind(dataSource);
121         boundName = lookupName;
122         final Properties environment = InMemoryJndiContextFactory.environment();
123         final JndiDatabaseTester tester =
124                 new JndiDatabaseTester(environment, lookupName, null, new CachingConnectionProvider());
125 
126         tester.getConnection();
127         tester.getConnection().getConnection().close();
128         final IDatabaseConnection third = tester.getConnection();
129 
130         openedConnection = third;
131         assertThat(InMemoryJndiContextFactory.lookupCount(lookupName))
132                 .as("JndiDatabaseTester's pre-existing initialize()/initialized-flag memoization "
133                         + "must still resolve the DataSource via JNDI only once, even across "
134                         + "multiple getConnection() calls and a CachingConnectionProvider "
135                         + "replacing a dead connection in between.")
136                 .isEqualTo(1);
137     }
138 
139     private JndiDatabaseTester tester(final CachingConnectionProvider provider)
140     {
141         final String lookupName = InMemoryJndiContextFactory.bind(newDataSource());
142         boundName = lookupName;
143         final Properties environment = InMemoryJndiContextFactory.environment();
144         return new JndiDatabaseTester(environment, lookupName, null, provider);
145     }
146 
147     private static JdbcDataSource newDataSource()
148     {
149         final JdbcDataSource dataSource = new JdbcDataSource();
150         dataSource.setUrl(
151                 "jdbc:h2:mem:jnditester_" + DB_COUNTER.incrementAndGet() + ";DB_CLOSE_DELAY=-1");
152         return dataSource;
153     }
154 }