View Javadoc
1   package org.apache.onami.persist;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import de.bechte.junit.runners.context.HierarchicalContextRunner;
23  import org.aopalliance.intercept.MethodInvocation;
24  import org.junit.Before;
25  import org.junit.Test;
26  import org.junit.runner.RunWith;
27  import org.mockito.InOrder;
28  
29  import static org.hamcrest.CoreMatchers.sameInstance;
30  import static org.junit.Assert.assertThat;
31  import static org.junit.Assert.fail;
32  import static org.mockito.Mockito.doReturn;
33  import static org.mockito.Mockito.doThrow;
34  import static org.mockito.Mockito.inOrder;
35  import static org.mockito.Mockito.mock;
36  import static org.mockito.Mockito.never;
37  import static org.mockito.Mockito.verify;
38  
39  /**
40   * Test for {@link TxnInterceptor}
41   */
42  @RunWith(HierarchicalContextRunner.class)
43  public class TxnInterceptorTest
44  {
45  
46      private UnitOfWork unitOfWork;
47  
48      private TransactionalAnnotationHelper txnAnnotationHelper;
49  
50      private TransactionFacadeFactory tfProvider;
51  
52      private TransactionFacade txnFacade;
53  
54      private TxnInterceptor sut;
55  
56      private MethodInvocation invocation;
57  
58      @Before
59      public void setUp()
60          throws Exception
61      {
62          unitOfWork = mock( UnitOfWork.class );
63          tfProvider = mock( TransactionFacadeFactory.class );
64          txnAnnotationHelper = mock( TransactionalAnnotationHelper.class );
65  
66          sut = new TxnInterceptor();
67          sut.init( unitOfWork, tfProvider, txnAnnotationHelper );
68  
69          invocation = mock( MethodInvocation.class );
70      }
71  
72      public class NotParticipatingInTransaction
73      {
74  
75          @Before
76          public void setUp()
77              throws Exception
78          {
79              doReturn( false ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
80          }
81  
82          @Test
83          public void invokesOriginalIfNotParticipatingInTransaction()
84              throws Throwable
85          {
86              sut.invoke( invocation );
87  
88              verify( invocation ).proceed();
89          }
90  
91      }
92  
93      public class ParticipatingInTransaction
94      {
95  
96          @Before
97          public void setUp()
98              throws Exception
99          {
100             doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
101 
102             txnFacade = mock( TransactionFacade.class );
103             doReturn( txnFacade ).when( tfProvider ).createTransactionFacade();
104         }
105 
106         public class UnitOfWorkInactive
107         {
108 
109             private InOrder inOrder;
110 
111             @Before
112             public void setup()
113             {
114                 doReturn( false ).when( unitOfWork ).isActive();
115                 inOrder = inOrder( unitOfWork, invocation );
116             }
117 
118             @Test
119             public void processWithoutException()
120                 throws Throwable
121             {
122                 sut.invoke( invocation );
123 
124                 inOrder.verify( unitOfWork ).begin();
125                 inOrder.verify( invocation ).proceed();
126                 inOrder.verify( unitOfWork ).end();
127             }
128 
129             @Test
130             public void processWithException()
131                 throws Throwable
132             {
133                 // given
134                 final RuntimeException originalException = new RuntimeException();
135                 doThrow( originalException ).when( invocation ).proceed();
136 
137                 // when
138                 try
139                 {
140                     sut.invoke( invocation );
141                 }
142 
143                 // then
144                 catch ( RuntimeException e )
145                 {
146                     inOrder.verify( unitOfWork ).begin();
147                     inOrder.verify( invocation ).proceed();
148                     inOrder.verify( unitOfWork ).end();
149                     assertThat( e, sameInstance( originalException ) );
150                     return;
151                 }
152                 fail( "expected RuntimeException to be thrown" );
153             }
154 
155             @Test
156             public void throwExceptionWhichOccurredInUnitOfWork()
157                 throws Throwable
158             {
159                 // given
160                 final RuntimeException uowExec = new RuntimeException();
161                 doThrow( uowExec ).when( unitOfWork ).end();
162 
163                 // when
164                 try
165                 {
166                     sut.invoke( invocation );
167                 }
168 
169                 // then
170                 catch ( RuntimeException e )
171                 {
172                     inOrder.verify( unitOfWork ).begin();
173                     inOrder.verify( invocation ).proceed();
174                     inOrder.verify( unitOfWork ).end();
175                     assertThat( e, sameInstance( uowExec ) );
176                     return;
177                 }
178                 fail( "expected RuntimeException to be thrown" );
179             }
180 
181             @Test
182             public void throwExceptionOfOriginalMethodIfExceptionOccurredInUnitOfWork()
183                 throws Throwable
184             {
185                 // given
186                 final RuntimeException originalExc = new RuntimeException();
187                 doThrow( originalExc ).when( invocation ).proceed();
188                 doThrow( new RuntimeException() ).when( unitOfWork ).end();
189 
190                 // when
191                 try
192                 {
193                     sut.invoke( invocation );
194                 }
195 
196                 // then
197                 catch ( RuntimeException e )
198                 {
199                     inOrder.verify( unitOfWork ).begin();
200                     inOrder.verify( invocation ).proceed();
201                     inOrder.verify( unitOfWork ).end();
202                     assertThat( e, sameInstance( originalExc ) );
203                     return;
204                 }
205                 fail( "expected RuntimeException to be thrown" );
206             }
207 
208         }
209 
210         public class UnitOfWorkActive
211         {
212 
213             private InOrder inOrder;
214 
215             @Before
216             public void setup()
217             {
218                 doReturn( true ).when( unitOfWork ).isActive();
219                 inOrder = inOrder( txnFacade, invocation );
220             }
221 
222             @Test
223             public void processWithoutUnitOfWork()
224                 throws Throwable
225             {
226                 sut.invoke( invocation );
227 
228                 verify( unitOfWork, never() ).begin();
229                 verify( invocation ).proceed();
230                 verify( unitOfWork, never() ).end();
231             }
232 
233             @Test
234             public void invokeStartsTransactionIfParticipatingInTransaction()
235                 throws Throwable
236             {
237                 // given
238                 doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
239                 // when
240                 sut.invoke( invocation );
241                 // then
242                 inOrder.verify( txnFacade ).begin();
243                 inOrder.verify( invocation ).proceed();
244                 inOrder.verify( txnFacade ).commit();
245             }
246 
247             @Test
248             public void rollbackIfExceptionThrownWhichRequiresRollback()
249                 throws Throwable
250             {
251                 // given
252                 final RuntimeException exc = new RuntimeException();
253                 doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
254                 doThrow( exc ).when( invocation ).proceed();
255                 doReturn( true ).when( txnAnnotationHelper ).isRollbackNecessaryFor( invocation, exc );
256 
257                 // when
258                 try
259                 {
260                     sut.invoke( invocation );
261                 }
262 
263                 // then
264                 catch ( RuntimeException e )
265                 {
266                     inOrder.verify( txnFacade ).begin();
267                     inOrder.verify( invocation ).proceed();
268                     inOrder.verify( txnFacade ).rollback();
269                     assertThat( e, sameInstance( exc ) );
270                     return;
271                 }
272                 fail( "expected RuntimeException to be thrown" );
273             }
274 
275             @Test
276             public void commitIfExceptionThrownWhichRequiresNoRollback()
277                 throws Throwable
278             {
279                 // given
280                 final RuntimeException exc = new RuntimeException();
281                 doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
282                 doThrow( exc ).when( invocation ).proceed();
283                 doReturn( false ).when( txnAnnotationHelper ).isRollbackNecessaryFor( invocation, exc );
284 
285                 // when
286                 try
287                 {
288                     sut.invoke( invocation );
289                 }
290 
291                 // then
292                 catch ( RuntimeException e )
293                 {
294                     inOrder.verify( txnFacade ).begin();
295                     inOrder.verify( invocation ).proceed();
296                     inOrder.verify( txnFacade ).commit();
297                     assertThat( e, sameInstance( exc ) );
298                     return;
299                 }
300                 fail( "expected RuntimeException to be thrown" );
301             }
302 
303             @Test
304             public void throwExceptionOfOriginalMethodIfExceptionOccurredInCommit()
305                 throws Throwable
306             {
307                 // given
308                 final RuntimeException exc = new RuntimeException();
309                 doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
310                 doThrow( exc ).when( invocation ).proceed();
311                 doReturn( false ).when( txnAnnotationHelper ).isRollbackNecessaryFor( invocation, exc );
312                 doThrow( new RuntimeException() ).when( txnFacade ).commit();
313 
314                 // when
315                 try
316                 {
317                     sut.invoke( invocation );
318                 }
319 
320                 // then
321                 catch ( RuntimeException e )
322                 {
323                     inOrder.verify( txnFacade ).begin();
324                     inOrder.verify( invocation ).proceed();
325                     inOrder.verify( txnFacade ).commit();
326                     assertThat( e, sameInstance( exc ) );
327                     return;
328                 }
329                 fail( "expected RuntimeException to be thrown" );
330             }
331 
332             @Test
333             public void throwExceptionOfOriginalMethodIfExceptionOccurredInRollback()
334                 throws Throwable
335             {
336                 // given
337                 final RuntimeException exc = new RuntimeException();
338                 doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
339                 doThrow( exc ).when( invocation ).proceed();
340                 doReturn( true ).when( txnAnnotationHelper ).isRollbackNecessaryFor( invocation, exc );
341                 doThrow( new RuntimeException() ).when( txnFacade ).rollback();
342 
343                 // when
344                 try
345                 {
346                     sut.invoke( invocation );
347                 }
348 
349                 // then
350                 catch ( RuntimeException e )
351                 {
352                     inOrder.verify( txnFacade ).begin();
353                     inOrder.verify( invocation ).proceed();
354                     inOrder.verify( txnFacade ).rollback();
355                     assertThat( e, sameInstance( exc ) );
356                     return;
357                 }
358                 fail( "expected RuntimeException to be thrown" );
359             }
360 
361         }
362 
363     }
364 
365 }