1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.dbunit;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24
25 import java.util.ArrayList;
26 import java.util.HashSet;
27 import java.util.List;
28
29 import org.dbunit.database.CachingConnectionProvider;
30 import org.dbunit.database.IDatabaseConnection;
31 import org.dbunit.dataset.IDataSet;
32 import org.dbunit.operation.DatabaseOperation;
33 import org.dbunit.util.fileloader.DataFileLoader;
34 import org.dbunit.util.fileloader.FlatXmlDataFileLoader;
35 import org.junit.jupiter.api.BeforeEach;
36 import org.junit.jupiter.api.Test;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 class DatabaseTesterConnectionReuseIT
56 {
57 private DatabaseProfile profile;
58
59 @BeforeEach
60 void setUp() throws Exception
61 {
62 profile = DatabaseEnvironment.getInstance().getProfile();
63 }
64
65 @Test
66 void testOnSetupAndOnTearDown_acrossFreshTesterInstancesSharingAProviderAndNoOpListener_reuseOneConnection()
67 throws Exception
68 {
69 final CachingConnectionProvider sharedProvider = new CachingConnectionProvider();
70 final List<IDatabaseConnection> connectionsUsed = new ArrayList<>();
71 try
72 {
73 for (int simulatedTestMethod = 0; simulatedTestMethod < 3; simulatedTestMethod++)
74 {
75 final IDatabaseTester tester = newSharedProviderTester(sharedProvider);
76 tester.setOperationListener(IOperationListener.NO_OP_OPERATION_LISTENER);
77 tester.setSetUpOperation(capturingOperation(connectionsUsed));
78 tester.setTearDownOperation(capturingOperation(connectionsUsed));
79
80 tester.onSetup();
81 tester.onTearDown();
82 }
83
84 assertThat(connectionsUsed)
85 .as("Precondition: setUp+tearDown across 3 simulated test methods must have "
86 + "executed an operation, and therefore captured a connection, 6 times.")
87 .hasSize(6);
88 assertThat(new HashSet<>(connectionsUsed))
89 .as("Every onSetup()/onTearDown() call across 3 simulated test methods - each "
90 + "building its own fresh IDatabaseTester, exactly as DatabaseTestCase "
91 + "does per test - must share the one connection cached by the "
92 + "CachingConnectionProvider they all point at, since a "
93 + "NO_OP_OPERATION_LISTENER keeps it from ever being closed between "
94 + "calls.")
95 .hasSize(1);
96 } finally
97 {
98 sharedProvider.close();
99 }
100 }
101
102 @Test
103 void testOnSetupAndOnTearDown_acrossFreshTesterInstancesSharingAProviderWithDefaultListener_staysOptInAndCreatesFreshConnectionsEveryTime()
104 throws Exception
105 {
106 final CachingConnectionProvider sharedProvider = new CachingConnectionProvider();
107 final List<IDatabaseConnection> connectionsUsed = new ArrayList<>();
108 try
109 {
110 for (int simulatedTestMethod = 0; simulatedTestMethod < 2; simulatedTestMethod++)
111 {
112 final IDatabaseTester tester = newSharedProviderTester(sharedProvider);
113
114
115 tester.setSetUpOperation(capturingOperation(connectionsUsed));
116 tester.setTearDownOperation(capturingOperation(connectionsUsed));
117
118 tester.onSetup();
119 tester.onTearDown();
120 }
121
122 assertThat(connectionsUsed)
123 .as("Precondition: setUp+tearDown across 2 simulated test methods must have "
124 + "captured a connection 4 times.")
125 .hasSize(4);
126 assertThat(new HashSet<>(connectionsUsed))
127 .as("Opting into a CachingConnectionProvider without also switching away from "
128 + "the library's default closing IOperationListener must stay fully "
129 + "backward compatible: every call still observes a freshly "
130 + "(re)created connection, exactly like not using a provider at all.")
131 .hasSize(4);
132 } finally
133 {
134 sharedProvider.close();
135 }
136 }
137
138 @Test
139 void testDefaultPrepAndExpectedTestCase_acrossFreshInstancesSharingAProviderWithCloseDisabled_reusesOneConnection()
140 throws Exception
141 {
142 final CachingConnectionProvider sharedProvider = new CachingConnectionProvider();
143 final List<IDatabaseConnection> connectionsUsed = new ArrayList<>();
144 try
145 {
146 for (int simulatedTestMethod = 0; simulatedTestMethod < 3; simulatedTestMethod++)
147 {
148 final IDatabaseTester tester = newSharedProviderTester(sharedProvider);
149 final DefaultPrepAndExpectedTestCase tc = newTestCase(tester);
150 tc.setCloseConnectionAfterTest(false);
151
152 tc.configureTest(new VerifyTableDefinition[] {}, new String[] {},
153 new String[] {});
154 tc.preTest();
155 tc.postTest();
156
157 connectionsUsed.add(tester.getConnection());
158 }
159
160 assertThat(new HashSet<>(connectionsUsed))
161 .as("With closing disabled, DefaultPrepAndExpectedTestCase must not close the "
162 + "connection a shared CachingConnectionProvider still has cached, so "
163 + "3 simulated test methods - each building its own fresh tester and "
164 + "test case pointed at the same provider - must all observe the same "
165 + "underlying connection (issue #800/#801).")
166 .hasSize(1);
167 } finally
168 {
169 sharedProvider.close();
170 }
171 }
172
173 @Test
174 void testDefaultPrepAndExpectedTestCase_acrossFreshInstancesSharingAProviderWithDefaultConfiguration_createsFreshConnectionsEveryTime()
175 throws Exception
176 {
177 final CachingConnectionProvider sharedProvider = new CachingConnectionProvider();
178 final List<IDatabaseConnection> connectionsUsed = new ArrayList<>();
179 try
180 {
181 for (int simulatedTestMethod = 0; simulatedTestMethod < 2; simulatedTestMethod++)
182 {
183 final IDatabaseTester tester = newSharedProviderTester(sharedProvider);
184 final DefaultPrepAndExpectedTestCase tc = newTestCase(tester);
185
186
187 tc.configureTest(new VerifyTableDefinition[] {}, new String[] {},
188 new String[] {});
189 tc.preTest();
190 tc.postTest();
191
192 connectionsUsed.add(tester.getConnection());
193 }
194
195 assertThat(new HashSet<>(connectionsUsed))
196 .as("Left at its default, DefaultPrepAndExpectedTestCase must stay fully "
197 + "backward compatible: cleanupData() closes the connection it used, "
198 + "so the CachingConnectionProvider must hand back a freshly "
199 + "(re)created one to the next simulated test method, exactly like not "
200 + "sharing a provider at all.")
201 .hasSize(2);
202 } finally
203 {
204 sharedProvider.close();
205 }
206 }
207
208 @Test
209 void testDefaultPrepAndExpectedTestCase_reusedAcrossTestMethodsWithCloseDisabled_keepsReusingItsOneOpenConnection()
210 throws Exception
211 {
212 final CachingConnectionProvider provider = new CachingConnectionProvider();
213 final IDatabaseTester tester = newSharedProviderTester(provider);
214 tester.setTearDownOperation(DatabaseOperation.DELETE_ALL);
215 final DefaultPrepAndExpectedTestCase tc = newCloseDisabledTestCase(tester);
216 final List<IDatabaseConnection> connectionsSeen = new ArrayList<>();
217 try
218 {
219 for (int simulatedTestMethod = 0; simulatedTestMethod < 3; simulatedTestMethod++)
220 {
221 runOneSimulatedTestMethod(tc);
222
223 final IDatabaseConnection connection = tester.getConnection();
224 connectionsSeen.add(connection);
225 assertThat(connection.getConnection().isClosed())
226 .as("closeConnectionAfterTest=false: the connection must still be"
227 + " open for the next simulated test method to reuse.")
228 .isFalse();
229 }
230
231 assertThat(new HashSet<>(connectionsSeen))
232 .as("One DefaultPrepAndExpectedTestCase reused across test methods, backed"
233 + " by a CachingConnectionProvider, must run every method against"
234 + " the one cached connection while it stays alive.")
235 .hasSize(1);
236 } finally
237 {
238 provider.close();
239 }
240 }
241
242 @Test
243 void testDefaultPrepAndExpectedTestCase_reusedWithCloseDisabled_whenItsCachedConnectionDiesBetweenTestMethods_replacesItRatherThanReusingTheDeadOne()
244 throws Exception
245 {
246 final CachingConnectionProvider provider = new CachingConnectionProvider();
247 final IDatabaseTester tester = newSharedProviderTester(provider);
248 tester.setTearDownOperation(DatabaseOperation.DELETE_ALL);
249 final DefaultPrepAndExpectedTestCase tc = newCloseDisabledTestCase(tester);
250 try
251 {
252
253 runOneSimulatedTestMethod(tc);
254 final IDatabaseConnection firstConnection = tester.getConnection();
255
256
257
258
259 firstConnection.getConnection().close();
260
261
262
263
264
265 runOneSimulatedTestMethod(tc);
266
267 final IDatabaseConnection secondConnection = tester.getConnection();
268 assertThat(secondConnection.getConnection().isClosed())
269 .as("The reused test case must have replaced the connection killed"
270 + " between test methods, not kept handing back the dead one.")
271 .isFalse();
272 assertThat(secondConnection)
273 .as("A fresh connection must have been acquired from the"
274 + " CachingConnectionProvider once the first one died.")
275 .isNotSameAs(firstConnection);
276 } finally
277 {
278 provider.close();
279 }
280 }
281
282 private DefaultPrepAndExpectedTestCase newTestCase(final IDatabaseTester tester)
283 {
284 final DataFileLoader dataFileLoader = new FlatXmlDataFileLoader();
285 return new DefaultPrepAndExpectedTestCase(dataFileLoader, tester);
286 }
287
288 private DefaultPrepAndExpectedTestCase newCloseDisabledTestCase(final IDatabaseTester tester)
289 {
290 final DefaultPrepAndExpectedTestCase tc = newTestCase(tester);
291 tc.setCloseConnectionAfterTest(false);
292 return tc;
293 }
294
295 private static void runOneSimulatedTestMethod(final DefaultPrepAndExpectedTestCase tc)
296 throws Exception
297 {
298 tc.runTest(new VerifyTableDefinition[] {}, new String[] {}, new String[] {},
299 () -> null);
300 }
301
302 private IDatabaseTester newSharedProviderTester(final CachingConnectionProvider sharedProvider)
303 throws Exception
304 {
305 return new JdbcDatabaseTester(profile.getDriverClass(), profile.getConnectionUrl(),
306 profile.getUser(), profile.getPassword(), profile.getSchema(), sharedProvider);
307 }
308
309
310
311
312
313
314 private static DatabaseOperation capturingOperation(final List<IDatabaseConnection> capturedInto)
315 {
316 return new DatabaseOperation()
317 {
318 @Override
319 public void execute(final IDatabaseConnection connection, final IDataSet dataSet)
320 {
321 capturedInto.add(connection);
322 }
323 };
324 }
325 }