/** * Copyright (c) 2014 - 2017 Frank Appel * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Frank Appel - initial API and implementation */ package com.codeaffine.workflow.internal; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import com.codeaffine.workflow.definition.Activity; import com.codeaffine.workflow.definition.ActivityAspect; import com.codeaffine.workflow.definition.Retry; public class ActivityExecutorTest { private static final int DELAY = 500; private Activity activity; private ActivityExecutor activityExecutor; static class RetryActivity implements Activity { private final Activity delegate; RetryActivity( Activity delegate ) { this.delegate = delegate; } @Override @Retry( on = IllegalStateException.class, delay = DELAY, times = 1 ) public void execute() { delegate.execute(); } } @Before public void setUp() { activity = mock( Activity.class ); activityExecutor = new ActivityExecutor(); } @Test public void testExecute() { activityExecutor.execute( activity ); verify( activity ).execute(); } @Test public void testExecuteWithProblem() { RuntimeException toBeThrown = equipActivityWithIllegalStateException(); try { activityExecutor.execute( activity ); fail(); } catch( RuntimeException expected ) { assertSame( toBeThrown, expected ); } } @Test public void testExecuteWithAspect() { ActivityAspect aspect = equipExecutorWithMockedAspect(); activityExecutor.execute( activity ); InOrder order = inOrder( aspect, activity ); order.verify( aspect ).beforeExecute( activity ); order.verify( activity ).execute(); order.verify( aspect ).afterExecute( activity, null ); order.verifyNoMoreInteractions(); } @Test public void testExecuteWithRetryAnnotation() { ActivityAspect aspect = equipExecutorWithMockedAspect(); RuntimeException expected = equipActivityWithIllegalStateException(); RetryActivity retryActivity = new RetryActivity( activity ); long start = System.currentTimeMillis(); try { activityExecutor.execute( retryActivity ); fail(); } catch( RuntimeException actual ) { long duration = System.currentTimeMillis() - start; assertSame( expected, actual ); assertTrue( duration >= DELAY ); InOrder order = inOrder( aspect, activity ); order.verify( aspect ).beforeExecute( retryActivity ); order.verify( activity, times( 2 ) ).execute(); order.verify( aspect ).afterExecute( retryActivity, expected ); order.verifyNoMoreInteractions(); } } @Test public void testExecuteWithRetryAnnotationAndUncaughtException() { ActivityAspect aspect = equipExecutorWithMockedAspect(); RuntimeException expected = equipActivityWithRuntimeException(); RetryActivity retryActivity = new RetryActivity( activity ); long start = System.currentTimeMillis(); try { activityExecutor.execute( retryActivity ); fail(); } catch( RuntimeException actual ) { long duration = System.currentTimeMillis() - start; assertTrue( duration < DELAY ); assertSame( expected, actual ); InOrder order = inOrder( aspect, activity ); order.verify( aspect ).beforeExecute( retryActivity ); order.verify( activity ).execute(); order.verify( aspect ).afterExecute( retryActivity, expected ); order.verifyNoMoreInteractions(); } } @Test public void testExecuteWithAspectAndProblem() { RuntimeException toBeThrown = equipActivityWithIllegalStateException(); ActivityAspect aspect = equipExecutorWithMockedAspect(); try { activityExecutor.execute( activity ); fail(); } catch( RuntimeException expected ) { InOrder order = inOrder( aspect, activity ); order.verify( aspect ).beforeExecute( activity ); order.verify( activity ).execute(); order.verify( aspect ).afterExecute( activity, toBeThrown ); order.verifyNoMoreInteractions(); assertSame( toBeThrown, expected ); } } @Test public void testExecuteWithProblemInBeforeExecute() { ActivityAspect aspect = equipExecutorWithMockedAspect(); RuntimeException toBeThrown = equipBeforeExecuteWithProblem( aspect ); try { activityExecutor.execute( activity ); fail(); } catch( RuntimeException expected ) { InOrder order = inOrder( aspect, activity ); order.verify( aspect ).beforeExecute( activity ); order.verifyNoMoreInteractions(); assertSame( toBeThrown, expected ); } } @Test public void testExecuteWithProblemInAfterExecute() { ActivityAspect aspect = equipExecutorWithMockedAspect(); RuntimeException toBeThrown = equipAfterExecuteWithProblem( aspect ); try { activityExecutor.execute( activity ); fail(); } catch( RuntimeException expected ) { InOrder order = inOrder( aspect, activity ); order.verify( aspect ).beforeExecute( activity ); order.verify( activity ).execute(); order.verify( aspect ).afterExecute( activity, null ); order.verifyNoMoreInteractions(); assertSame( toBeThrown, expected ); } } private RuntimeException equipActivityWithIllegalStateException() { return equipActivityWithProblem( new IllegalStateException( "Problem in execute." ) ); } private RuntimeException equipActivityWithRuntimeException() { return equipActivityWithProblem( new RuntimeException( "Problem in execute." ) ); } private RuntimeException equipActivityWithProblem( RuntimeException result ) { doThrow( result ).when( activity ).execute(); return result; } private ActivityAspect equipExecutorWithMockedAspect() { ActivityAspect result = mock( ActivityAspect.class ); activityExecutor.add( result ); return result; } private RuntimeException equipBeforeExecuteWithProblem( ActivityAspect aspect ) { RuntimeException result = new RuntimeException( "Problem in beforeExecute." ); doThrow( result ).when( aspect ).beforeExecute( activity ); return result; } private RuntimeException equipAfterExecuteWithProblem( ActivityAspect aspect ) { RuntimeException result = new RuntimeException( "Problem in afterExecute." ); doThrow( result ).when( aspect ).afterExecute( activity, null ); return result; } }