1 package org.apache.onami.persist;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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
134 final RuntimeException originalException = new RuntimeException();
135 doThrow( originalException ).when( invocation ).proceed();
136
137
138 try
139 {
140 sut.invoke( invocation );
141 }
142
143
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
160 final RuntimeException uowExec = new RuntimeException();
161 doThrow( uowExec ).when( unitOfWork ).end();
162
163
164 try
165 {
166 sut.invoke( invocation );
167 }
168
169
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
186 final RuntimeException originalExc = new RuntimeException();
187 doThrow( originalExc ).when( invocation ).proceed();
188 doThrow( new RuntimeException() ).when( unitOfWork ).end();
189
190
191 try
192 {
193 sut.invoke( invocation );
194 }
195
196
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
238 doReturn( true ).when( txnAnnotationHelper ).persistenceUnitParticipatesInTransactionFor( invocation );
239
240 sut.invoke( invocation );
241
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
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
258 try
259 {
260 sut.invoke( invocation );
261 }
262
263
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
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
286 try
287 {
288 sut.invoke( invocation );
289 }
290
291
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
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
315 try
316 {
317 sut.invoke( invocation );
318 }
319
320
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
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
344 try
345 {
346 sut.invoke( invocation );
347 }
348
349
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 }