View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.dbutils;
18  
19  import static org.junit.Assert.fail;
20  import static org.mockito.ArgumentMatchers.any;
21  import static org.mockito.ArgumentMatchers.eq;
22  import static org.mockito.Mockito.doThrow;
23  import static org.mockito.Mockito.mock;
24  import static org.mockito.Mockito.never;
25  import static org.mockito.Mockito.times;
26  import static org.mockito.Mockito.verify;
27  import static org.mockito.Mockito.when;
28  
29  import java.sql.CallableStatement;
30  import java.sql.Connection;
31  import java.sql.ParameterMetaData;
32  import java.sql.PreparedStatement;
33  import java.sql.ResultSet;
34  import java.sql.ResultSetMetaData;
35  import java.sql.SQLException;
36  import java.sql.Statement;
37  import java.sql.Types;
38  import java.util.ArrayList;
39  import java.util.List;
40  
41  import javax.sql.DataSource;
42  
43  import org.apache.commons.dbutils.handlers.ArrayHandler;
44  import org.apache.commons.dbutils.handlers.ScalarHandler;
45  import org.junit.Assert;
46  import org.junit.Before;
47  import org.junit.Test;
48  import org.junit.runner.RunWith;
49  import org.mockito.Mock;
50  import org.mockito.invocation.InvocationOnMock;
51  import org.mockito.junit.MockitoJUnitRunner;
52  import org.mockito.stubbing.Answer;
53  
54  @SuppressWarnings("boxing") // test code
55  @RunWith(MockitoJUnitRunner.class)
56  public class QueryRunnerTest {
57      //
58      // Random tests
59      //
60      class MyBean {
61          private int a;
62          private double b;
63          private String c;
64  
65          public int getA() {    return a; }
66          public double getB() { return b; }
67          public String getC() { return c; }
68          public void setA(final int a) { this.a = a; }
69          public void setB(final double b) { this.b = b; }
70          public void setC(final String c) { this.c = c; }
71      }
72      QueryRunner runner;
73  
74      ArrayHandler handler;
75      @Mock DataSource dataSource;
76      @Mock Connection conn;
77      @Mock PreparedStatement prepStmt;
78      @Mock Statement stmt;
79      @Mock CallableStatement call;
80      @Mock ParameterMetaData meta;
81      @Mock ResultSet results;
82  
83      @Mock ResultSetMetaData resultsMeta;
84  
85      //
86      // Batch test cases
87      //
88  
89      // helper method for calling batch when an exception is expected
90      private void callBatchWithException(final String sql, final Object[][] params) throws Exception {
91          when(meta.getParameterCount()).thenReturn(2);
92          boolean caught = false;
93  
94          try {
95              runner.batch(sql, params);
96  
97              verify(prepStmt, times(1)).getParameterMetaData();
98              verify(prepStmt, times(2)).addBatch();
99              verify(prepStmt, times(1)).executeBatch();
100             verify(prepStmt, times(1)).close();    // make sure the statement is closed
101             verify(conn, times(1)).close();    // make sure the connection is closed
102         } catch (final SQLException e) {
103             System.out.println("[TEST] The following exception is expected:");
104             System.out.println(e);
105             caught = true;
106         }
107 
108         if (!caught) {
109             fail("Exception never thrown, but expected");
110         }
111     }
112 
113     // helper method for calling execute when an exception is expected
114     private void callExecuteWithException(final Object... params) throws Exception {
115         boolean caught = false;
116 
117         try {
118             when(meta.getParameterCount()).thenReturn(2);
119             runner.query("{call my_proc(?, ?)}", handler, params);
120 
121         } catch (final SQLException e) {
122             caught = true;
123         }
124 
125         if (!caught) {
126             fail("Exception never thrown, but expected");
127         }
128     }
129 
130     // helper method for calling execute when an exception is expected
131     private void callExecuteWithResultSetWithException(final Object... params) throws Exception {
132         boolean caught = false;
133 
134         try {
135             when(meta.getParameterCount()).thenReturn(2);
136             runner.execute("{call my_proc(?, ?)}", handler, params);
137 
138         } catch (final SQLException e) {
139             caught = true;
140         }
141 
142         if (!caught) {
143             fail("Exception never thrown, but expected");
144         }
145     }
146 
147 
148     private void callGoodBatch(final Connection conn, final Object[][] params) throws Exception {
149         when(meta.getParameterCount()).thenReturn(2);
150         runner.batch(conn, "select * from blah where ? = ?", params);
151 
152         verify(prepStmt, times(1)).getParameterMetaData();
153         verify(prepStmt, times(2)).addBatch();
154         verify(prepStmt, times(1)).executeBatch();
155         verify(prepStmt, times(1)).close();    // make sure we closed the statement
156         verify(conn, times(0)).close();    // make sure we do not close the connection, since QueryRunner.batch(Connection, String, Object[][]) does not close connections
157     }
158 
159     private void callGoodBatch(final Object[][] params) throws Exception {
160         callGoodBatch(params, true);
161     }
162 
163     private void callGoodBatch(final Object[][] params, final boolean pmdCheck) throws Exception {
164         when(meta.getParameterCount()).thenReturn(2);
165         runner.batch("select * from blah where ? = ?", params);
166 
167         verify(prepStmt, times(pmdCheck ? 1 : 0)).getParameterMetaData();
168         verify(prepStmt, times(2)).addBatch();
169         verify(prepStmt, times(1)).executeBatch();
170         verify(prepStmt, times(1)).close();    // make sure we closed the statement
171         verify(conn, times(1)).close();    // make sure we closed the connection
172     }
173 
174     private void callGoodExecute() throws Exception {
175         when(call.execute()).thenReturn(false);
176         when(call.getUpdateCount()).thenReturn(3);
177 
178         when(meta.getParameterCount()).thenReturn(2);
179         int result = runner.execute("{call my_proc(?, ?)}", "unit", "test");
180 
181         Assert.assertEquals(3, result);
182 
183         verify(call, times(1)).execute();
184         verify(call, times(1)).close();    // make sure we closed the statement
185         verify(conn, times(1)).close();    // make sure we do not close the connection
186 
187         // call the other variation of query
188         when(meta.getParameterCount()).thenReturn(0);
189         result = runner.execute("{call my_proc()}");
190 
191         Assert.assertEquals(3, result);
192 
193         verify(call, times(2)).execute();
194         verify(call, times(2)).close();    // make sure we closed the statement
195         verify(conn, times(2)).close();    // make sure we do not close the connection
196 
197         // Test single OUT parameter
198         when(meta.getParameterCount()).thenReturn(1);
199         when(call.getObject(1)).thenReturn(42);
200         final OutParameter<Integer> intParam =
201             new OutParameter<>(Types.INTEGER, Integer.class);
202         result = runner.execute("{?= call my_proc()}", intParam);
203 
204         Assert.assertEquals(42, intParam.getValue().intValue());
205         Assert.assertEquals(3, result);
206 
207         verify(call, times(3)).execute();
208         verify(call, times(3)).close();    // make sure we closed the statement
209         verify(conn, times(3)).close();    // make sure we do not close the connection
210 
211         // Test OUT parameters with IN parameters
212         when(meta.getParameterCount()).thenReturn(3);
213         when(call.getObject(1)).thenReturn(4242);
214         intParam.setValue(null);
215         result = runner.execute("{?= call my_proc(?, ?)}", intParam, "unit", "test");
216 
217         Assert.assertEquals(4242, intParam.getValue().intValue());
218         Assert.assertEquals(3, result);
219 
220         verify(call, times(4)).execute();
221         verify(call, times(4)).close();    // make sure we closed the statement
222         verify(conn, times(4)).close();    // make sure we do not close the connection
223 
224         // Test INOUT parameters
225         when(meta.getParameterCount()).thenReturn(3);
226         when(call.getObject(1)).thenReturn(24);
227         when(call.getObject(3)).thenReturn("out");
228         intParam.setValue(null);
229         final OutParameter<String> stringParam =
230             new OutParameter<>(Types.VARCHAR, String.class, "in");
231         result = runner.execute("{?= call my_proc(?, ?)}", intParam, "test", stringParam);
232 
233         Assert.assertEquals(24, intParam.getValue().intValue());
234         Assert.assertEquals("out", stringParam.getValue());
235         Assert.assertEquals(3, result);
236 
237         verify(call, times(5)).execute();
238         verify(call, times(5)).close();    // make sure we closed the statement
239         verify(conn, times(5)).close();    // make sure we do not close the connection
240     }
241 
242 
243     //
244     // Execute tests
245     //
246     private void callGoodExecute(final Connection conn) throws Exception {
247         when(call.execute()).thenReturn(false);
248         when(call.getUpdateCount()).thenReturn(3);
249 
250         when(meta.getParameterCount()).thenReturn(2);
251         int result = runner.execute(conn, "{call my_proc(?, ?)}", "unit", "test");
252 
253         Assert.assertEquals(3, result);
254 
255         verify(call, times(1)).execute();
256         verify(call, times(1)).close();    // make sure we closed the statement
257         verify(conn, times(0)).close();    // make sure we do not close the connection
258 
259         // call the other variation of query
260         when(meta.getParameterCount()).thenReturn(0);
261         result = runner.execute(conn, "{call my_proc()}");
262 
263         Assert.assertEquals(3, result);
264 
265         verify(call, times(2)).execute();
266         verify(call, times(2)).close();    // make sure we closed the statement
267         verify(conn, times(0)).close();    // make sure we do not close the connection
268 
269         // Test single OUT parameter
270         when(meta.getParameterCount()).thenReturn(1);
271         when(call.getObject(1)).thenReturn(42);
272         final OutParameter<Integer> intParam =
273             new OutParameter<>(Types.INTEGER, Integer.class);
274         result = runner.execute(conn, "{?= call my_proc()}", intParam);
275 
276         Assert.assertEquals(42, intParam.getValue().intValue());
277         Assert.assertEquals(3, result);
278 
279         verify(call, times(3)).execute();
280         verify(call, times(3)).close();    // make sure we closed the statement
281         verify(conn, times(0)).close();    // make sure we do not close the connection
282 
283         // Test OUT parameters with IN parameters
284         when(meta.getParameterCount()).thenReturn(3);
285         when(call.getObject(1)).thenReturn(4242);
286         intParam.setValue(null);
287         result = runner.execute(conn, "{?= call my_proc(?, ?)}", intParam, "unit", "test");
288 
289         Assert.assertEquals(4242, intParam.getValue().intValue());
290         Assert.assertEquals(3, result);
291 
292         verify(call, times(4)).execute();
293         verify(call, times(4)).close();    // make sure we closed the statement
294         verify(conn, times(0)).close();    // make sure we do not close the connection
295 
296         // Test INOUT parameters
297         when(meta.getParameterCount()).thenReturn(3);
298         when(call.getObject(1)).thenReturn(24);
299         when(call.getObject(3)).thenReturn("out");
300         intParam.setValue(null);
301         final OutParameter<String> stringParam =
302             new OutParameter<>(Types.VARCHAR, String.class, "in");
303         result = runner.execute(conn, "{?= call my_proc(?, ?)}", intParam, "test", stringParam);
304 
305         Assert.assertEquals(24, intParam.getValue().intValue());
306         Assert.assertEquals("out", stringParam.getValue());
307         Assert.assertEquals(3, result);
308 
309         verify(call, times(5)).execute();
310         verify(call, times(5)).close();    // make sure we closed the statement
311         verify(conn, times(0)).close();    // make sure we do not close the connection
312     }
313 
314     private void callGoodExecuteWithResultSet() throws Exception {
315         when(call.execute()).thenReturn(true);
316 
317         when(meta.getParameterCount()).thenReturn(2);
318         runner.execute("{call my_proc(?, ?)}", handler, "unit", "test");
319 
320         verify(call, times(1)).execute();
321         verify(results, times(1)).close();
322         verify(call, times(1)).close();    // make sure we closed the statement
323         verify(conn, times(1)).close();    // make sure we do not close the connection
324 
325         // call the other variation of query
326         when(meta.getParameterCount()).thenReturn(0);
327         runner.execute("{call my_proc()}", handler);
328 
329         verify(call, times(2)).execute();
330         verify(results, times(2)).close();
331         verify(call, times(2)).close();    // make sure we closed the statement
332         verify(conn, times(2)).close();    // make sure we do not close the connection
333 
334         // Test single OUT parameter
335         when(meta.getParameterCount()).thenReturn(1);
336         when(call.getObject(1)).thenReturn(42);
337         final OutParameter<Integer> intParam =
338             new OutParameter<>(Types.INTEGER, Integer.class);
339         runner.execute("{?= call my_proc()}", handler, intParam);
340 
341         Assert.assertEquals(42, intParam.getValue().intValue());
342 
343         verify(call, times(3)).execute();
344         verify(results, times(3)).close();
345         verify(call, times(3)).close();    // make sure we closed the statement
346         verify(conn, times(3)).close();    // make sure we do not close the connection
347 
348         // Test OUT parameters with IN parameters
349         when(meta.getParameterCount()).thenReturn(3);
350         when(call.getObject(1)).thenReturn(4242);
351         intParam.setValue(null);
352         runner.execute("{?= call my_proc(?, ?)}", handler, intParam, "unit", "test");
353 
354         Assert.assertEquals(4242, intParam.getValue().intValue());
355 
356         verify(call, times(4)).execute();
357         verify(results, times(4)).close();
358         verify(call, times(4)).close();    // make sure we closed the statement
359         verify(conn, times(4)).close();    // make sure we do not close the connection
360 
361         // Test INOUT parameters
362         when(meta.getParameterCount()).thenReturn(3);
363         when(call.getObject(1)).thenReturn(24);
364         when(call.getObject(3)).thenReturn("out");
365         intParam.setValue(null);
366         final OutParameter<String> stringParam =
367             new OutParameter<>(Types.VARCHAR, String.class, "in");
368         runner.execute("{?= call my_proc(?, ?)}", handler, intParam, "test", stringParam);
369 
370         Assert.assertEquals(24, intParam.getValue().intValue());
371         Assert.assertEquals("out", stringParam.getValue());
372 
373         verify(call, times(5)).execute();
374         verify(results, times(5)).close();
375         verify(call, times(5)).close();    // make sure we closed the statement
376         verify(conn, times(5)).close();    // make sure we do not close the connection
377     }
378 
379     private void callGoodExecuteWithResultSet(final Connection conn) throws Exception {
380         when(call.execute()).thenReturn(true);
381 
382         when(meta.getParameterCount()).thenReturn(2);
383         runner.execute(conn, "{call my_proc(?, ?)}", handler, "unit", "test");
384 
385         verify(call, times(1)).execute();
386         verify(results, times(1)).close();
387         verify(call, times(1)).close();    // make sure we closed the statement
388         verify(conn, times(0)).close();    // make sure we do not close the connection
389 
390         // call the other variation of query
391         when(meta.getParameterCount()).thenReturn(0);
392         runner.execute(conn, "{call my_proc()}", handler);
393 
394         verify(call, times(2)).execute();
395         verify(results, times(2)).close();
396         verify(call, times(2)).close();    // make sure we closed the statement
397         verify(conn, times(0)).close();    // make sure we do not close the connection
398 
399         // Test single OUT parameter
400         when(meta.getParameterCount()).thenReturn(1);
401         when(call.getObject(1)).thenReturn(42);
402         final OutParameter<Integer> intParam =
403             new OutParameter<>(Types.INTEGER, Integer.class);
404         runner.execute(conn, "{?= call my_proc()}", handler, intParam);
405 
406         Assert.assertEquals(42, intParam.getValue().intValue());
407 
408         verify(call, times(3)).execute();
409         verify(results, times(3)).close();
410         verify(call, times(3)).close();    // make sure we closed the statement
411         verify(conn, times(0)).close();    // make sure we do not close the connection
412 
413         // Test OUT parameters with IN parameters
414         when(meta.getParameterCount()).thenReturn(3);
415         when(call.getObject(1)).thenReturn(4242);
416         intParam.setValue(null);
417         runner.execute(conn, "{?= call my_proc(?, ?)}", handler, intParam, "unit", "test");
418 
419         Assert.assertEquals(4242, intParam.getValue().intValue());
420 
421         verify(call, times(4)).execute();
422         verify(results, times(4)).close();
423         verify(call, times(4)).close();    // make sure we closed the statement
424         verify(conn, times(0)).close();    // make sure we do not close the connection
425 
426         // Test INOUT parameters
427         when(meta.getParameterCount()).thenReturn(3);
428         when(call.getObject(1)).thenReturn(24);
429         when(call.getObject(3)).thenReturn("out");
430         intParam.setValue(null);
431         final OutParameter<String> stringParam =
432             new OutParameter<>(Types.VARCHAR, String.class, "in");
433         runner.execute(conn, "{?= call my_proc(?, ?)}", handler, intParam, "test", stringParam);
434 
435         Assert.assertEquals(24, intParam.getValue().intValue());
436         Assert.assertEquals("out", stringParam.getValue());
437 
438         verify(call, times(5)).execute();
439         verify(results, times(5)).close();
440         verify(call, times(5)).close();    // make sure we closed the statement
441         verify(conn, times(0)).close();    // make sure we do not close the connection
442     }
443 
444     private void callGoodQuery() throws Exception {
445         when(meta.getParameterCount()).thenReturn(2);
446         String sql = "select * from blah where ? = ?";
447         runner.query(sql, handler, "unit", "test");
448 
449         verify(prepStmt, times(1)).executeQuery();
450         verify(results, times(1)).close();
451         verify(prepStmt, times(1)).close();    // make sure we closed the statement
452         verify(conn, times(1)).close();    // make sure we closed the connection
453 
454         // call the other variation of query
455         sql = "select * from blah";
456         runner.query(sql, handler);
457 
458         verify(stmt, times(1)).executeQuery(sql);
459         verify(results, times(2)).close();
460         verify(stmt, times(1)).close();    // make sure we closed the statement
461         verify(conn, times(2)).close();    // make sure we closed the connection
462     }
463 
464 
465     //
466     // Query test cases
467     //
468     private void callGoodQuery(final Connection conn) throws Exception {
469         when(meta.getParameterCount()).thenReturn(2);
470         String sql = "select * from blah where ? = ?";
471         runner.query(conn, sql, handler, "unit", "test");
472 
473         verify(prepStmt, times(1)).executeQuery();
474         verify(results, times(1)).close();
475         verify(prepStmt, times(1)).close();    // make sure we closed the statement
476         verify(conn, times(0)).close();    // make sure we do not close the connection, since QueryRunner.query(Connection, String, ResultSetHandler<T>, Object...) does not close connections
477 
478         // call the other variation of query
479         sql = "select * from blah";
480         runner.query(conn, sql, handler);
481 
482         verify(stmt, times(1)).executeQuery(sql);
483         verify(results, times(2)).close();
484         verify(stmt, times(1)).close();    // make sure we closed the statement
485         verify(conn, times(0)).close();    // make sure we do not close the connection, see above
486     }
487 
488 
489     private void callGoodUpdate() throws Exception {
490         when(meta.getParameterCount()).thenReturn(2);
491         String sql = "update blah set ? = ?";
492         runner.update(sql, "unit", "test");
493 
494         verify(prepStmt, times(1)).executeUpdate();
495         verify(prepStmt, times(1)).close();    // make sure we closed the statement
496         verify(conn, times(1)).close();    // make sure we closed the connection
497 
498         // call the other variation
499         when(meta.getParameterCount()).thenReturn(0);
500         sql = "update blah set unit = test";
501         runner.update(sql);
502 
503         verify(stmt, times(1)).executeUpdate(sql);
504         verify(stmt, times(1)).close();    // make sure we closed the statement
505         verify(conn, times(2)).close();    // make sure we closed the connection
506 
507         // call the other variation
508         when(meta.getParameterCount()).thenReturn(1);
509         sql = "update blah set unit = ?";
510         runner.update(sql, "test");
511 
512         verify(prepStmt, times(2)).executeUpdate();
513         verify(prepStmt, times(2)).close();    // make sure we closed the statement
514         verify(conn, times(3)).close();    // make sure we closed the connection
515     }
516 
517     //
518     // Update test cases
519     //
520     private void callGoodUpdate(final Connection conn) throws Exception {
521         when(meta.getParameterCount()).thenReturn(2);
522         runner.update(conn, "update blah set ? = ?", "unit", "test");
523 
524         verify(prepStmt, times(1)).executeUpdate();
525         verify(prepStmt, times(1)).close();    // make sure we closed the statement
526         verify(conn, times(0)).close();    // make sure we do not close the connection, since QueryRunner.update(Connection, String, Object...) does not close connections
527 
528         // call the other variation
529         when(meta.getParameterCount()).thenReturn(0);
530         final String sql = "update blah set unit = test";
531         runner.update(conn, sql);
532 
533         verify(stmt, times(1)).executeUpdate(sql);
534         verify(stmt, times(1)).close();    // make sure we closed the statement
535         verify(conn, times(0)).close();    // make sure we do not close the connection, see above
536 
537         // call the other variation
538         when(meta.getParameterCount()).thenReturn(1);
539         runner.update(conn, "update blah set unit = ?", "test");
540 
541         verify(prepStmt, times(2)).executeUpdate();
542         verify(prepStmt, times(2)).close();    // make sure we closed the statement
543         verify(conn, times(0)).close();    // make sure we do not close the connection, see above
544     }
545 
546     // helper method for calling batch when an exception is expected
547     private void callQueryWithException(final Object... params) throws Exception {
548         boolean caught = false;
549 
550         try {
551             when(meta.getParameterCount()).thenReturn(2);
552             final String sql = "select * from blah where ? = ?";
553             runner.query(sql, handler, params);
554 
555             verify(prepStmt, never()).close();    // make sure the statement is still open
556             verify(prepStmt, times(1)).executeQuery();
557             verify(prepStmt, times(1)).close();    // make sure we closed the statement
558             verify(results, times(1)).close();
559             verify(conn, times(1)).close();    // make sure we closed the connection
560         } catch (final SQLException e) {
561             caught = true;
562         }
563 
564         if (!caught) {
565             fail("Exception never thrown, but expected");
566         }
567     }
568 
569 
570 
571     // helper method for calling batch when an exception is expected
572     private void callUpdateWithException(final Object... params) throws Exception {
573         boolean caught = false;
574 
575         try {
576             when(meta.getParameterCount()).thenReturn(2);
577             final String sql = "select * from blah where ? = ?";
578             runner.update(sql, params);
579 
580             verify(prepStmt, times(1)).executeUpdate();
581             verify(prepStmt, times(1)).close();    // make sure we closed the statement
582             verify(conn, times(1)).close();    // make sure we closed the connection
583         } catch (final SQLException e) {
584             caught = true;
585         }
586 
587         if (!caught) {
588             fail("Exception never thrown, but expected");
589         }
590     }
591 
592     @Before
593     public void setUp() throws Exception {
594         when(dataSource.getConnection()).thenReturn(conn);
595 
596         when(conn.prepareStatement(any(String.class))).thenReturn(prepStmt);
597         when(prepStmt.getParameterMetaData()).thenReturn(meta);
598         when(prepStmt.executeQuery()).thenReturn(results);
599 
600         when(conn.createStatement()).thenReturn(stmt);
601         when(stmt.executeQuery(any(String.class))).thenReturn(results);
602 
603         when(conn.prepareCall(any(String.class))).thenReturn(call);
604         when(call.getParameterMetaData()).thenReturn(meta);
605         when(call.getResultSet()).thenReturn(results);
606         when(call.getMoreResults()).thenReturn(false);
607 
608         when(results.next()).thenReturn(false);
609 
610          handler = new ArrayHandler();
611          runner = new QueryRunner(dataSource);
612     }
613 
614     @Test
615     public void testAddBatchExceptionOnAdd() throws Exception {
616         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
617 
618         doThrow(new SQLException()).when(prepStmt).addBatch();
619 
620         callBatchWithException("select * from blah where ? = ?", params);
621     }
622 
623     @Test(expected=SQLException.class)
624     public void testBadPrepareConnection() throws Exception {
625         runner = new QueryRunner();
626         runner.update("update blah set unit = test");
627     }
628 
629     @Test
630     public void testExecuteBatchExceptionOnExec() throws Exception {
631         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
632 
633         doThrow(new SQLException()).when(prepStmt).executeBatch();
634 
635         callBatchWithException("select * from blah where ? = ?", params);
636     }
637 
638 
639     @Test
640     public void testExecuteException() throws Exception {
641         callExecuteWithException(handler, "unit", "test");
642     }
643 
644     @Test
645     public void testExecuteQueryException() throws Exception {
646         callQueryWithException(handler, "unit", "test");
647     }
648 
649     @Test
650     public void testExecuteUpdateException() throws Exception {
651         doThrow(new SQLException()).when(prepStmt).executeUpdate();
652 
653         callUpdateWithException("unit", "test");
654     }
655 
656     @Test
657     public void testExecuteWithMultipleResultSets() throws Exception {
658         when(call.execute()).thenReturn(true);
659         when(call.getMoreResults()).thenAnswer(new Answer<Boolean>()
660         {
661             int count = 1;
662             @Override
663             public Boolean answer(final InvocationOnMock invocation)
664             {
665                 return ++count <= 3;
666             }
667         });
668         when(meta.getParameterCount()).thenReturn(0);
669         final List<Object[]> objects = runner.execute("{call my_proc()}", handler);
670 
671         Assert.assertEquals(3, objects.size());
672         verify(call, times(1)).execute();
673         verify(results, times(3)).close();
674         verify(call, times(1)).close();    // make sure we closed the statement
675         verify(conn, times(1)).close();    // make sure we close the connection
676 
677     }
678 
679     @Test
680     public void testExecuteWithResultSetException() throws Exception {
681         callExecuteWithResultSetWithException(handler, "unit", "test");
682     }
683 
684     @Test
685     public void testFillStatementWithBean() throws Exception {
686         final MyBean bean = new MyBean();
687         when(meta.getParameterCount()).thenReturn(3);
688         runner.fillStatementWithBean(prepStmt, bean, "a", "b", "c");
689     }
690 
691     @Test(expected=NullPointerException.class)
692     public void testFillStatementWithBeanNullNames() throws Exception {
693         final MyBean bean = new MyBean();
694         runner.fillStatementWithBean(prepStmt, bean, "a", "b", null);
695     }
696 
697     @Test
698     public void testGoodBatch() throws Exception {
699         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
700 
701         callGoodBatch(params);
702     }
703 
704 
705     @Test
706     public void testGoodBatchDefaultConstructor() throws Exception {
707         runner = new QueryRunner();
708         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
709 
710         callGoodBatch(conn, params);
711     }
712 
713     @Test
714     public void testGoodBatchInsert() throws Exception {
715         results = mock(ResultSet.class);
716         resultsMeta = mock(ResultSetMetaData.class);
717 
718         when(meta.getParameterCount()).thenReturn(2);
719         when(conn.prepareStatement(any(String.class), eq(Statement.RETURN_GENERATED_KEYS))).thenReturn(prepStmt);
720         when(prepStmt.getGeneratedKeys()).thenReturn(results);
721         when(results.next()).thenReturn(true).thenReturn(true).thenReturn(false);
722 
723         final ResultSetHandler<List<Object>> handler = rs -> {
724             final List<Object> objects = new ArrayList<>();
725             while (rs.next())
726             {
727                 objects.add(new Object());
728             }
729             return objects;
730         };
731 
732         final Object[][] params = new Object[2][2];
733         params[0][0] = "Test";
734         params[0][1] = "Blah";
735         params[1][0] = "Test2";
736         params[1][1] = "Blah2";
737 
738         final List<Object> generatedKeys = runner.insertBatch("INSERT INTO blah(col1, col2) VALUES(?,?)", handler, params);
739 
740         verify(prepStmt, times(2)).addBatch();
741         verify(prepStmt, times(1)).executeBatch();
742         verify(prepStmt, times(1)).close();    // make sure we closed the statement
743         verify(conn, times(1)).close();    // make sure we closed the connection
744 
745         Assert.assertEquals(2, generatedKeys.size());
746     }
747 
748     @Test
749     public void testGoodBatchPmdTrue() throws Exception {
750         runner = new QueryRunner(dataSource, true);
751         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
752 
753         callGoodBatch(params, false);
754     }
755 
756     @Test
757     public void testGoodExecute() throws Exception {
758         callGoodExecute();
759     }
760 
761     @Test
762     public void testGoodExecuteDefaultConstructor() throws Exception {
763         runner = new QueryRunner();
764         callGoodExecute(conn);
765     }
766 
767     @Test
768     public void testGoodExecutePmdTrue() throws Exception {
769         runner = new QueryRunner(true);
770         callGoodExecute(conn);
771     }
772 
773     @Test
774     public void testGoodExecuteWithResultSet() throws Exception {
775         callGoodExecuteWithResultSet();
776     }
777 
778     @Test
779     public void testGoodExecuteWithResultSetDefaultConstructor() throws Exception {
780         runner = new QueryRunner();
781         callGoodExecuteWithResultSet(conn);
782     }
783 
784     @Test
785     public void testGoodExecuteWithResultSetPmdTrue() throws Exception {
786         runner = new QueryRunner(true);
787         callGoodExecuteWithResultSet(conn);
788     }
789 
790     @Test
791     public void testGoodInsert() throws Exception {
792         results = mock(ResultSet.class);
793 
794         when(meta.getParameterCount()).thenReturn(2);
795         when(conn.prepareStatement(any(String.class), eq(Statement.RETURN_GENERATED_KEYS))).thenReturn(prepStmt);
796         when(prepStmt.getGeneratedKeys()).thenReturn(results);
797         when(results.next()).thenReturn(true).thenReturn(false);
798         when(results.getObject(1)).thenReturn(1L);
799 
800         final Long generatedKey = runner.insert("INSERT INTO blah(col1, col2) VALUES(?,?)", new ScalarHandler<>(), "unit", "test");
801 
802         verify(prepStmt, times(1)).executeUpdate();
803         verify(prepStmt, times(1)).close();    // make sure we closed the statement
804         verify(conn, times(1)).close();    // make sure we closed the connection
805 
806         Assert.assertEquals(1L, generatedKey.longValue());
807     }
808 
809     @Test
810     public void testGoodQuery() throws Exception {
811         callGoodQuery();
812     }
813 
814     @Test
815     public void testGoodQueryDefaultConstructor() throws Exception {
816         runner = new QueryRunner();
817         callGoodQuery(conn);
818     }
819 
820     @Test
821     public void testGoodQueryPmdTrue() throws Exception {
822         runner = new QueryRunner(true);
823         callGoodQuery(conn);
824     }
825 
826     @Test
827     public void testGoodUpdate() throws Exception {
828         callGoodUpdate();
829     }
830 
831     @Test
832     public void testGoodUpdateDefaultConstructor() throws Exception {
833         runner = new QueryRunner();
834         callGoodUpdate(conn);
835     }
836 
837     @Test
838     public void testGoodUpdatePmdTrue() throws Exception {
839         runner = new QueryRunner(true);
840         callGoodUpdate(conn);
841     }
842 
843     @Test
844     public void testNoParamsExecute() throws Exception {
845         callGoodExecute();
846     }
847 
848     @Test
849     public void testNoParamsExecuteWithResultSet() throws Exception {
850         callExecuteWithResultSetWithException();
851     }
852 
853     @Test
854     public void testNoParamsQuery() throws Exception {
855         callGoodQuery();
856     }
857 
858     @Test
859     public void testNoParamsUpdate() throws Exception {
860         callGoodUpdate();
861     }
862 
863     @Test(expected=SQLException.class)
864     public void testNullConnectionBatch() throws Exception {
865         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
866 
867         when(dataSource.getConnection()).thenReturn(null);
868 
869         runner.batch("select * from blah where ? = ?", params);
870     }
871 
872     @Test(expected=SQLException.class)
873     public void testNullConnectionExecute() throws Exception {
874         when(dataSource.getConnection()).thenReturn(null);
875 
876         runner.execute("{call my_proc(?, ?)}", "unit", "test");
877     }
878 
879     @Test(expected=SQLException.class)
880     public void testNullConnectionExecuteWithResultSet() throws Exception {
881         when(dataSource.getConnection()).thenReturn(null);
882 
883         runner.execute("{call my_proc(?, ?)}", handler, "unit", "test");
884     }
885 
886     @Test(expected=SQLException.class)
887     public void testNullConnectionQuery() throws Exception {
888         when(dataSource.getConnection()).thenReturn(null);
889 
890         runner.query("select * from blah where ? = ?", handler, "unit", "test");
891     }
892 
893     @Test(expected=SQLException.class)
894     public void testNullConnectionUpdate() throws Exception {
895         when(dataSource.getConnection()).thenReturn(null);
896 
897         runner.update("select * from blah where ? = ?", "unit", "test");
898     }
899 
900     @Test(expected=SQLException.class)
901     public void testNullHandlerExecute() throws Exception {
902         when(meta.getParameterCount()).thenReturn(2);
903 
904         runner.execute("{call my_proc(?, ?)}");
905     }
906 
907     @Test(expected=SQLException.class)
908     public void testNullHandlerExecuteWithResultSet() throws Exception {
909         runner.execute("{call my_proc(?, ?)}", (ResultSetHandler)null);
910     }
911 
912     @Test(expected=SQLException.class)
913     public void testNullHandlerQuery() throws Exception {
914         runner.query("select * from blah where ? = ?", null);
915     }
916 
917     //
918     // Execute with ResultSetHandler
919     //
920 
921     @Test(expected=SQLException.class)
922     public void testNullParamsArgBatch() throws Exception {
923         runner.batch("select * from blah where ? = ?", null);
924     }
925 
926     @Test
927     public void testNullParamsBatch() throws Exception {
928         final String[][] params = { { null, "unit" }, { "test", null } };
929 
930         callGoodBatch(params);
931     }
932 
933     @Test(expected=SQLException.class)
934     public void testNullSqlBatch() throws Exception {
935         final String[][] params = { { "unit", "unit" }, { "test", "test" } };
936 
937         runner.batch(null, params);
938     }
939 
940     @Test(expected=SQLException.class)
941     public void testNullSqlExecute() throws Exception {
942         runner.execute(null);
943     }
944 
945     @Test(expected=SQLException.class)
946     public void testNullSqlExecuteWithResultSet() throws Exception {
947         runner.execute(null, handler);
948     }
949 
950     @Test(expected=SQLException.class)
951     public void testNullSqlQuery() throws Exception {
952         runner.query(null, handler);
953     }
954 
955     @Test(expected=SQLException.class)
956     public void testNullSqlUpdate() throws Exception {
957         runner.update(null);
958     }
959 
960     @Test
961     public void testStatementConfiguration() throws Exception {
962         final StatementConfiguration stmtConfig = new StatementConfiguration(1, 2, 3, 4, 5);
963         final QueryRunner queryRunner = new QueryRunner(stmtConfig);
964         queryRunner.prepareStatement(conn, "select 1");
965 
966         verify(prepStmt).setFetchDirection(eq(1));
967         verify(prepStmt).setFetchSize(eq(2));
968         verify(prepStmt).setMaxFieldSize(eq(3));
969         verify(prepStmt).setMaxRows(eq(4));
970         verify(prepStmt).setQueryTimeout(eq(5));
971     }
972 
973     @Test
974     public void testTooFewParamsBatch() throws Exception {
975         final String[][] params = { { "unit" }, { "test" } };
976 
977         callBatchWithException("select * from blah where ? = ?", params);
978     }
979 
980     @Test
981     public void testTooFewParamsExecute() throws Exception {
982         callExecuteWithException("unit");
983     }
984 
985     @Test
986     public void testTooFewParamsExecuteWithResultSet() throws Exception {
987         callExecuteWithResultSetWithException("unit");
988     }
989 
990     @Test
991     public void testTooFewParamsQuery() throws Exception {
992         callQueryWithException("unit");
993     }
994 
995     @Test
996     public void testTooFewParamsUpdate() throws Exception {
997         callUpdateWithException("unit");
998     }
999 
1000     @Test
1001     public void testTooManyParamsBatch() throws Exception {
1002         final String[][] params = { { "unit", "unit", "unit" }, { "test", "test", "test" } };
1003 
1004         callBatchWithException("select * from blah where ? = ?", params);
1005     }
1006 
1007     @Test
1008     public void testTooManyParamsExecute() throws Exception {
1009         callExecuteWithException("unit", "test", "fail");
1010     }
1011 
1012     @Test
1013     public void testTooManyParamsExecuteWithResultSet() throws Exception {
1014         callExecuteWithResultSetWithException("unit", "test", "fail");
1015     }
1016 
1017     @Test
1018     public void testTooManyParamsQuery() throws Exception {
1019         callQueryWithException("unit", "test", "fail");
1020     }
1021 
1022     @Test
1023     public void testTooManyParamsUpdate() throws Exception {
1024         callUpdateWithException("unit", "test", "fail");
1025     }
1026 }