/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.message.processing;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mule.api.exception.SystemExceptionHandler;
import org.mule.execution.EndPhaseTemplate;
import org.mule.execution.EndProcessPhase;
import org.mule.execution.MessageProcessContext;
import org.mule.execution.MessageProcessPhase;
import org.mule.execution.MessageProcessTemplate;
import org.mule.execution.PhaseExecutionEngine;
import org.mule.execution.PhaseResultNotifier;
import org.mule.tck.size.SmallTest;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
@RunWith(MockitoJUnitRunner.class)
@SmallTest
public class PhaseExecutionEngineTestCase
{
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SystemExceptionHandler mockExceptionHandler;
private List<MessageProcessPhase> phaseList = new ArrayList<MessageProcessPhase>();
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private EndProcessPhase mockEndPhase;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private MessageProcessPhase mockProcessPhase1;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private MessageProcessPhase mockProcessPhase2;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private MessageProcessPhase mockProcessPhase3;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private MessageProcessPhase mockFailingPhase;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private EndPhaseTemplate mockTemplate;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private MessageProcessContext mockContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PhaseResultNotifier mockNotifier;
@Test
public void allPhasesRun() throws Exception
{
when(mockEndPhase.supportsTemplate(mockTemplate)).thenReturn(true);
verifyAllPhasesAreRun();
verify(mockEndPhase, Mockito.times(1)).runPhase(any(EndPhaseTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
}
@Test
public void endPhaseDoesNotRun() throws Exception
{
when(mockEndPhase.supportsTemplate(mockTemplate)).thenReturn(false);
verifyAllPhasesAreRun();
verify(mockEndPhase, Mockito.times(0)).runPhase(any(EndPhaseTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
}
@Test
public void exceptionHandlerIsCalledOnFailure() throws Exception
{
addSupportedPhase(mockFailingPhase);
addSupportedPhase(mockProcessPhase1);
when(mockEndPhase.supportsTemplate(mockTemplate)).thenReturn(true);
PhaseExecutionEngine phaseExecutionEngine = new PhaseExecutionEngine(phaseList, mockExceptionHandler, mockEndPhase);
phaseExecutionEngine.process(mockTemplate,mockContext);
verify(mockEndPhase,times(1)).runPhase(any(EndPhaseTemplate.class),any(MessageProcessContext.class), any(PhaseResultNotifier.class));
}
@Test
public void phaseItsNoSupportedThenNextPhaseExecutes() throws Exception
{
addSupportedPhase(mockProcessPhase1);
addNotSupportedPhase(mockProcessPhase2);
addSupportedPhase(mockProcessPhase3);
when(mockProcessPhase2.supportsTemplate(mockTemplate)).thenReturn(false);
PhaseExecutionEngine phaseExecutionEngine = new PhaseExecutionEngine(phaseList, mockExceptionHandler, mockEndPhase);
phaseExecutionEngine.process(mockTemplate, mockContext);
verify(mockProcessPhase1,times(1)).runPhase(any(EndPhaseTemplate.class),any(MessageProcessContext.class), any(PhaseResultNotifier.class));
verify(mockProcessPhase2,times(0)).runPhase(any(EndPhaseTemplate.class),any(MessageProcessContext.class), any(PhaseResultNotifier.class));
verify(mockProcessPhase3,times(1)).runPhase(any(EndPhaseTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
}
private void verifyAllPhasesAreRun()
{
PhaseExecutionEngine engine = new PhaseExecutionEngine(phaseList,mockExceptionHandler, mockEndPhase);
addAllPhases();
engine.process(mockTemplate, mockContext);
verify(mockProcessPhase1, Mockito.times(1)).runPhase(any(MessageProcessTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
verify(mockProcessPhase2, Mockito.times(1)).runPhase(any(MessageProcessTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
verify(mockProcessPhase3, Mockito.times(1)).runPhase(any(MessageProcessTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
}
private void addAllPhases()
{
addSupportedPhase(mockProcessPhase1);
addSupportedPhase(mockProcessPhase2);
addSupportedPhase(mockProcessPhase3);
}
private void addSupportedPhase(MessageProcessPhase mockProcessPhase)
{
addPhase(mockProcessPhase, true);
}
private void addNotSupportedPhase(MessageProcessPhase mockProcessPhase)
{
addPhase(mockProcessPhase, false);
}
private void addPhase(MessageProcessPhase mockProcessPhase, boolean supportsTemplate)
{
phaseList.add(mockProcessPhase);
when(mockProcessPhase.supportsTemplate(mockTemplate)).thenReturn(supportsTemplate);
Mockito.doAnswer(new Answer()
{
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable
{
((PhaseResultNotifier)invocationOnMock.getArguments()[2]).phaseSuccessfully();
return null;
}
}).when(mockProcessPhase).runPhase(any(MessageProcessTemplate.class), any(MessageProcessContext.class), any(PhaseResultNotifier.class));
}
}