View Javadoc

1   package com.atlassian.sal.core.rdbms;
2   
3   import com.atlassian.sal.api.rdbms.ConnectionCallback;
4   import com.atlassian.sal.spi.HostConnectionAccessor;
5   import org.junit.Before;
6   import org.junit.Rule;
7   import org.junit.Test;
8   import org.junit.rules.ExpectedException;
9   import org.junit.runner.RunWith;
10  import org.mockito.Mock;
11  import org.mockito.invocation.InvocationOnMock;
12  import org.mockito.runners.MockitoJUnitRunner;
13  import org.mockito.stubbing.Answer;
14  
15  import java.sql.Connection;
16  import java.sql.SQLException;
17  
18  import static org.hamcrest.Matchers.nullValue;
19  import static org.hamcrest.core.Is.is;
20  import static org.junit.Assert.assertThat;
21  import static org.mockito.Matchers.any;
22  import static org.mockito.Mockito.doThrow;
23  import static org.mockito.Mockito.never;
24  import static org.mockito.Mockito.verify;
25  import static org.mockito.Mockito.when;
26  
27  @RunWith (MockitoJUnitRunner.class)
28  public class TestDefaultTransactionalExecutor
29  {
30      @Rule
31      public ExpectedException expectedException = ExpectedException.none();
32  
33      private DefaultTransactionalExecutor defaultTransactionalExecutor;
34  
35      @Mock
36      private HostConnectionAccessor hostConnectionAccessor;
37      @Mock
38      private Connection connection;
39      @Mock
40      private ConnectionCallback<Object> callback;
41      @Mock
42      private Object result;
43  
44      private WrappedConnection wrappedConnection;
45  
46      private boolean callbackThrows;
47  
48      @Before
49      public void before()
50      {
51          defaultTransactionalExecutor = new DefaultTransactionalExecutor(hostConnectionAccessor, false, false);
52  
53          callbackThrows = false;
54  
55          // grab a hold of the wrapped connection each time
56          when(callback.execute(any(WrappedConnection.class))).thenAnswer(new Answer<Object>()
57          {
58              @Override
59              public Object answer(final InvocationOnMock invocation) throws Throwable
60              {
61                  wrappedConnection = (WrappedConnection) invocation.getArguments()[0];
62                  if (callbackThrows)
63                  {
64                      throw new RuntimeException("epic fail");
65                  }
66                  else
67                  {
68                      return result;
69                  }
70              }
71          });
72      }
73  
74      @Test
75      public void changeProperties()
76      {
77          defaultTransactionalExecutor.readOnly();
78          assertThat(defaultTransactionalExecutor.readOnly, is(true));
79  
80          defaultTransactionalExecutor.readWrite();
81          assertThat(defaultTransactionalExecutor.readOnly, is(false));
82  
83          defaultTransactionalExecutor.newTransaction();
84          assertThat(defaultTransactionalExecutor.newTransaction, is(true));
85  
86          defaultTransactionalExecutor.existingTransaction();
87          assertThat(defaultTransactionalExecutor.newTransaction, is(false));
88      }
89  
90      @Test
91      public void executeCommitSucceeds() throws SQLException
92      {
93          callbackThrows = false;
94  
95          assertThat(defaultTransactionalExecutor.executeInternal(connection, callback), is(result));
96          assertThat(wrappedConnection.connection, nullValue());
97  
98          verify(callback).execute(any(WrappedConnection.class));
99          verify(connection).commit();
100         verify(connection, never()).rollback();
101     }
102 
103     @Test
104     public void executeCommitFails() throws SQLException
105     {
106         callbackThrows = false;
107 
108         doThrow(new SQLException("horrible commit exception")).when(connection).commit();
109 
110         expectedException.expect(RuntimeException.class);
111         expectedException.expectCause(is(SQLException.class));
112 
113         defaultTransactionalExecutor.executeInternal(connection, callback);
114         assertThat(wrappedConnection.connection, nullValue());
115 
116         verify(callback).execute(any(WrappedConnection.class));
117         verify(connection).commit();
118         verify(connection, never()).rollback();
119     }
120 
121     @Test
122     public void executeRollbackSucceeds() throws SQLException
123     {
124         callbackThrows = true;
125 
126         expectedException.expect(RuntimeException.class);
127         expectedException.expectMessage("epic fail");
128 
129         defaultTransactionalExecutor.executeInternal(connection, callback);
130         assertThat(wrappedConnection.connection, nullValue());
131 
132         verify(callback).execute(any(WrappedConnection.class));
133         verify(connection, never()).commit();
134         verify(connection).rollback();
135     }
136 
137     @Test
138     public void executeRollbackFails() throws SQLException
139     {
140         callbackThrows = true;
141 
142         doThrow(new SQLException("horrible rollback exception")).when(connection).rollback();
143 
144         expectedException.expect(RuntimeException.class);
145         expectedException.expectMessage("epic fail");
146 
147         defaultTransactionalExecutor.executeInternal(connection, callback);
148         assertThat(wrappedConnection.connection, nullValue());
149 
150         verify(callback).execute(any(WrappedConnection.class));
151         verify(connection, never()).commit();
152         verify(connection).rollback();
153     }
154 
155     @Test
156     public void executeFailsOnAutoCommit() throws SQLException
157     {
158         when(connection.getAutoCommit()).thenReturn(true);
159 
160         expectedException.expect(IllegalStateException.class);
161 
162         defaultTransactionalExecutor.executeInternal(connection, callback);
163     }
164 
165     @Test
166     public void executeFailsOnAutoCommitGetFail() throws SQLException
167     {
168         when(connection.getAutoCommit()).thenThrow(new SQLException("horrible getAutoCommit exception"));
169 
170         expectedException.expect(RuntimeException.class);
171 
172         defaultTransactionalExecutor.executeInternal(connection, callback);
173     }
174 }