package net.ttddyy.dsproxy; import net.ttddyy.dsproxy.proxy.InterceptorHolder; import net.ttddyy.dsproxy.proxy.jdk.JdkJdbcProxyFactory; import org.assertj.core.api.Assertions; import org.junit.After; import org.junit.Before; import org.junit.Test; import javax.sql.DataSource; import java.sql.Connection; import java.sql.Statement; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; /** * @author Tadaya Tsuyukubo */ public class StatementInvocationHandlerTest { private DataSource jdbcDataSource; private TestListener testListener; private LastQueryListener lastQueryListener; private Statement statement; @Before public void setup() throws Exception { testListener = new TestListener(); lastQueryListener = new LastQueryListener(); InterceptorHolder interceptorHolder = new InterceptorHolder(); interceptorHolder.addListener(testListener); interceptorHolder.addListener(lastQueryListener); // real datasource jdbcDataSource = TestUtils.getDataSourceWithData(); Connection connection = jdbcDataSource.getConnection(); Statement stmt = connection.createStatement(); statement = new JdkJdbcProxyFactory().createStatement(stmt, interceptorHolder); } @After public void teardown() throws Exception { TestUtils.shutdown(jdbcDataSource); } @Test public void testException() throws Exception { final String query = "select * from emp;"; Exception ex = null; try { statement.executeUpdate(query); fail("select query with executeUpdate() should fail"); } catch (Exception e) { ex = e; } assertThat(ex, is(notNullValue())); assertThat(testListener.beforeCount, is(1)); assertThat(testListener.afterCount, is(1)); List<QueryInfo> beforeQueries = lastQueryListener.getBeforeQueries(); assertThat(beforeQueries, hasSize(1)); assertThat(beforeQueries.get(0).getQuery(), is(query)); List<QueryInfo> afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, hasSize(1)); assertThat(afterQueries.get(0).getQuery(), is(query)); ExecutionInfo afterExec = lastQueryListener.getAfterExecInfo(); assertThat(afterExec, is(notNullValue())); assertThat(afterExec.getThrowable(), is(notNullValue())); Throwable thrownException = afterExec.getThrowable(); assertThat(thrownException, sameInstance((Throwable) ex)); } @Test public void testExecuteQuery() throws Exception { final String query = "select * from emp;"; statement.executeQuery(query); assertThat(testListener.beforeCount, is(1)); assertThat(testListener.afterCount, is(1)); List<QueryInfo> beforeQueries = lastQueryListener.getBeforeQueries(); assertThat(beforeQueries, hasSize(1)); assertThat(beforeQueries.get(0).getQuery(), is(query)); List<QueryInfo> afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, hasSize(1)); assertThat(afterQueries.get(0).getQuery(), is(query)); } @Test public void testExecuteUpdate() throws Exception { final String query = "update emp set name = 'bar';"; statement.executeUpdate(query); assertThat(testListener.beforeCount, is(1)); assertThat(testListener.afterCount, is(1)); List<QueryInfo> beforeQueries = lastQueryListener.getBeforeQueries(); assertThat(beforeQueries, hasSize(1)); assertThat(beforeQueries.get(0).getQuery(), is(query)); List<QueryInfo> afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, hasSize(1)); assertThat(afterQueries.get(0).getQuery(), is(query)); } @Test public void testExecuteBatch() throws Exception { final String query1 = "insert into emp ( id, name ) values (3, 'baz');"; statement.addBatch(query1); assertThat(testListener.beforeCount, is(0)); assertThat(testListener.afterCount, is(0)); final String query2 = "update emp set name = 'FOO';"; statement.addBatch(query2); assertThat(testListener.beforeCount, is(0)); assertThat(testListener.afterCount, is(0)); int[] result = statement.executeBatch(); assertThat(testListener.beforeCount, is(1)); assertThat(testListener.afterCount, is(1)); assertThat(result.length, is(2)); assertThat("one row inserted", result[0], is(1)); assertThat("two rows updated", result[1], is(3)); List<QueryInfo> beforeQueries = lastQueryListener.getBeforeQueries(); assertThat(beforeQueries, hasSize(2)); assertThat(beforeQueries.get(0).getQuery(), is(query1)); assertThat(beforeQueries.get(1).getQuery(), is(query2)); List<QueryInfo> afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, hasSize(2)); assertThat(afterQueries.get(0).getQuery(), is(query1)); assertThat(afterQueries.get(1).getQuery(), is(query2)); } @Test public void testClearBatch() throws Exception { statement.addBatch("insert into emp ( id, name ) values (2, 'bar');"); assertThat(testListener.beforeCount, is(0)); assertThat(testListener.afterCount, is(0)); statement.clearBatch(); assertThat(testListener.beforeCount, is(0)); assertThat(testListener.afterCount, is(0)); List<QueryInfo> beforeQueries = lastQueryListener.getBeforeQueries(); assertThat(beforeQueries, hasSize(0)); List<QueryInfo> afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, hasSize(0)); } /** * When "executeBatch" is called, List<QueryInfo> should be cleared. * reported: https://github.com/ttddyy/datasource-proxy/issues/9 */ @Test public void testExecuteBatchShouldClearQueries() throws Exception { statement.addBatch("insert into emp ( id, name )values (100, 'FOO');"); statement.addBatch("insert into emp ( id, name )values (200, 'BAR');"); statement.executeBatch(); // 1st execution List<QueryInfo> afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, notNullValue()); assertThat("should pass two QueryInfo (FOO,BAR)", afterQueries, hasSize(2)); statement.addBatch("insert into emp ( id, name )values (300, 'BAZ');"); int[] updateCount = statement.executeBatch(); // 2nd execution assertThat(updateCount, notNullValue()); assertThat(updateCount.length, is(1)); // second execution should pass only one QueryInfo to listener afterQueries = lastQueryListener.getAfterQueries(); assertThat(afterQueries, notNullValue()); assertThat("should pass one QueryInfo (BAZ)", afterQueries, hasSize(1)); // verify actual data. 3 rows must be inserted, in addition to original data(2rows) int count = TestUtils.countTable(jdbcDataSource, "emp"); assertThat("2 existing data(foo,bar) and 3 insert(FOO,BAR,BAZ).", count, is(5)); } @Test public void sameInstanceOfExecutionInfo() throws Exception { final String query = "select * from emp;"; statement.executeQuery(query); ExecutionInfo before = lastQueryListener.getBeforeExecInfo(); ExecutionInfo after = lastQueryListener.getAfterExecInfo(); Assertions.assertThat(before).as("before and after uses same ExecutionInfo instance").isSameAs(after); } }