All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.soitoolkit.commons.mule.test.AbstractTestCase Maven / Gradle / Ivy

There is a newer version: 2.0.0-M6
Show newest version
/* 
 * Licensed to the soi-toolkit project under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The soi-toolkit project licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.soitoolkit.commons.mule.test;

import static org.mule.context.notification.ComponentMessageNotification.COMPONENT_POST_INVOKE;
import static org.mule.context.notification.ExceptionNotification.EXCEPTION_ACTION;

import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.mule.api.MuleMessage;
import org.mule.api.context.notification.ComponentMessageNotificationListener;
import org.mule.api.context.notification.EndpointMessageNotificationListener;
import org.mule.api.context.notification.ExceptionNotificationListener;
import org.mule.api.context.notification.ServerNotification;
// FIXME: Mule 3.1, no clue what we will get in case of exceptions...
// import org.mule.api.service.ServiceException;
import org.mule.context.notification.ComponentMessageNotification;
import org.mule.context.notification.EndpointMessageNotification;
import org.mule.context.notification.ExceptionNotification;
import org.mule.module.client.MuleClient;
import org.mule.tck.FunctionalTestCase;
import org.soitoolkit.commons.mule.util.MuleUtil;
import org.soitoolkit.commons.mule.util.ValueHolder;

/**
 * Extends the base class in Mule, org.mule.tck.FuntionalTestCase, i.e. for old-style junit3 testing
 * 
 * @deprecated since 0.5.0 use org.soitoolkit.commons.mule.test.junit4.AbstractTestCase instead for junit4 functionality
 * 
 * @author Magnus Larsson
 *
 */
public abstract class AbstractTestCase extends FunctionalTestCase {
    
    protected String junitTestCaseName;
    
    public AbstractTestCase() {
		super();

        // Activate the spring bean definition profile "soitoolkit-integrationtests"
        System.getProperties().put("spring.profiles.active", "soitoolkit-integrationtests");

		// Ensure that CXF use LOG4J for logging
		System.setProperty("org.apache.cxf.Logger", "org.apache.cxf.common.logging.Log4jLogger");
	}

	/**
     * Fix for Mule 2.2.2 problem with presentation of test-name i Eclipse
     * testrunner that comes from override in
     * org.mule.tck.AbstractMuleTestCase.setName(). 
     * 
     * @see org.mule.tck.AbstractMuleTestCase#getName()
     */
    @Override
    public String getName() {
      return junitTestCaseName;
    }

    /**
     * Fix for Mule 2.2.2 problem with presentation of test-name i Eclipse
     * testrunner that comes from override in
     * org.mule.tck.AbstractMuleTestCase.setName(). 
     * 
     * @see org.mule.tck.AbstractMuleTestCase#getName()
     */
    @Override
    public void setName(String name) {
        junitTestCaseName = name;
        super.setName(junitTestCaseName);
    }

    /**
     * Fix for Mule 2.2.2 where init of test timeout moved from setUp to
     * constructor. 
     * This method MUST be called from the constructor of an inherited TestCase
     * to have any effect, calling this method from doSetUp() or any other
     * method is too late.
     * 
     * @see org.mule.tck.AbstractMuleTestCase#AbstractMuleTestCase()
     * @see org.mule.tck.AbstractMuleTestCase#initTestTimeoutSecs()
     */
    /* ISSUE 156: use -Dmule.test.timeoutSecs=XX instead
    protected void setTestTimeoutSecs(int seconds) {
        logger.info("Setting test timeout to (seconds): " + seconds);
        String strSeconds = String.valueOf(seconds);
        System.setProperty(PROPERTY_MULE_TEST_TIMEOUT, strSeconds);
        initTestTimeoutSecs();	
    }
    */

	/**
	 * Sends the payload and headers to the inboundEndpointAddress and waits timeout ms for a MuleMessage to arrive on outboundEndpoint with the name outboundEndpointName. 
	 * 
	 * Sample usage:
	 * 
	 *	public void testTransferKorttransaktioner() throws Exception {
	 *		String expectedPayload = "Yada, yada, yada...";
	 *
	 *		MuleMessage message = dispatchAndWaitForDelivery(
	 *			"sftp://[email protected]/sftp/vfkonto/ut",
	 *			expectedPayload,
	 *			createFileHeader("from_vfkonto.dat"),
	 *			"volvokort-test-endpoint",
	 *			TIMEOUT);
	 *
	 *		String actualPayload = message.getPayloadAsString();
	 *		assertEquals(expectedPayload, actualPayload); 
	 *	}	 
	 * 
	 * 
	 * @param inboundEndpointAddress
	 * @param payload
	 * @param headers
	 * @param outboundEndpointName
	 * @param action as specified by org.mule.context.notification.EndpointMessageNotification: MESSAGE_RECEIVED, MESSAGE_DISPATCHED, MESSAGE_SENT or MESSAGE_REQUESTED
	 * @param timeout in ms
	 * @return the received MuleMEssage on the outboundEndpoint
	 */
	protected MuleMessage dispatchAndWaitForDelivery(String inboundEndpointAddress, Object payload, Map headers, final String outboundEndpointName, final int action, long timeout) {

		// Declare MuleMessage to return
		final ValueHolder receivedMessageHolder = new ValueHolder();
		
		// Declare countdown latch and listener
		final CountDownLatch latch = new CountDownLatch(1);
		EndpointMessageNotificationListener listener = null;
		MuleClient muleClient = null;

		try {
			// First create a muleClient instance
			muleClient = new MuleClient(muleContext);

			// Next create a listener that listens for dispatch events on the outbound endpoint
			listener = new EndpointMessageNotificationListener() {
				public void onNotification(ServerNotification notification) {
					if (logger.isDebugEnabled()) logger.debug("notification received on " + notification.getResourceIdentifier() + " (action: " + notification.getActionName() + ")");

					// Only care about EndpointMessageNotification
					if (notification instanceof EndpointMessageNotification) {
						EndpointMessageNotification endpointNotification = (EndpointMessageNotification)notification;

						// Extract action and name of the endpoint
						int    actualAction   = endpointNotification.getAction();
						String actualEndpoint = MuleUtil.getEndpointName(endpointNotification);

						// If it is a dispatch event on our outbound endpoint then countdown the latch.
						if (logger.isDebugEnabled()) {
							logger.debug(actualAction == action);
							logger.debug(actualEndpoint.equals(outboundEndpointName));
						}
						if (actualAction == action && actualEndpoint.equals(outboundEndpointName)) {
							if (logger.isDebugEnabled()) logger.debug("Expected notification received on " + actualEndpoint + " (action: " + endpointNotification.getActionName() + "), time to countdown the latch");
							receivedMessageHolder.value = (MuleMessage)endpointNotification.getSource();
							latch.countDown();

						} else {
							if (logger.isDebugEnabled()) logger.debug("A not matching notification received on " + actualEndpoint + " (action: " + endpointNotification.getActionName() + "), continue to wait for the right one...");							
						}
					}
				}
			};

			// Now register the listener
			muleContext.getNotificationManager().addListener(listener);

			// Perform the actual dispatch
			muleClient.dispatch(inboundEndpointAddress, payload, headers);

			// Wait for the delivery to occur...
			if (logger.isDebugEnabled()) logger.debug("Waiting for message to be delivered to the endpoint...");
			boolean workDone = latch.await(timeout, TimeUnit.MILLISECONDS);
			if (logger.isDebugEnabled()) logger.debug((workDone) ? "Message delivered, continue..." : "No message delivered, timeout occurred!");

			// Raise a fault if the test timed out
			assertTrue("Test timed out. It took more than " + timeout + " milliseconds. If this error occurs the test probably needs a longer time out (on your computer/network)", workDone);

		} catch (Exception e) {
			e.printStackTrace();
			fail("An unexpected error occurred: " + e.getMessage());

		} finally {
			// Dispose muleClient 
			muleClient.dispose();

			// Always remove the listener if created
			if (listener != null) muleContext.getNotificationManager().removeListener(listener);
		}
		
		return receivedMessageHolder.value;		
    }

	/**
	 * Waits timeout ms for a MuleMessage to be processed by a service component with the name serviceComponentName. 
	 * 
	 * Sample usage: TBS
	 * 
	 * @param serviceComponentName
	 * @param timeout in ms
	 * @return the MuleMessage sent to the named service component
	 */
	protected MuleMessage waitForServiceComponent(final String serviceComponentName, long timeout) {
		return dispatchAndWaitForServiceComponent(null, serviceComponentName, timeout);
    }

	/**
	 * Use the Dispatcher to send a asynchronous message and waits timeout ms for a MuleMessage to be processed by a service component with the name serviceComponentName. 
	 * 
	 * Sample usage: TBS
	 * 
	 * @param dispatcher
	 * @param serviceComponentName
	 * @param timeout in ms
	 * @return the MuleMessage sent to the named service component
	 */
	protected MuleMessage dispatchAndWaitForServiceComponent(Dispatcher dispatcher, final String serviceComponentName, long timeout) {
		// Declare MuleMessage to return
		final ValueHolder receivedMessageHolder = new ValueHolder();
		
		// Declare countdown latch and listener
		final CountDownLatch latch = new CountDownLatch(1);
		ComponentMessageNotificationListener listener = null;

		try {
			// Create a listener that listens for invoke events on the named component
			listener = new ComponentMessageNotificationListener() {
				public void onNotification(ServerNotification notification) {

					if (logger.isDebugEnabled()) logger.debug("notification received on " + notification.getResourceIdentifier() + " (action: " + notification.getActionName());

					// Only care about ComponentMessageNotification
					if (notification instanceof ComponentMessageNotification) {
						ComponentMessageNotification componentNotification = (ComponentMessageNotification)notification;

						// Extract action and name of the component
						int    action    = componentNotification.getAction();
						String component = componentNotification.getResourceIdentifier();

						// If it is a post-invoke event (i.e. the processing is done) on our component then countdown the latch.
						if (action == COMPONENT_POST_INVOKE && component.equals(serviceComponentName)) {
							if (logger.isDebugEnabled()) logger.debug("Expected notification received on " + serviceComponentName + " (action: " + componentNotification.getActionName() + "), time to countdown the latch");
							receivedMessageHolder.value = (MuleMessage)componentNotification.getSource();
							latch.countDown();
						}
					}
				}
			};

			// Now register the listener
			muleContext.getNotificationManager().addListener(listener);

			// Perform the actual dispatch, if any...
			if (dispatcher != null) {
				dispatcher.doDispatch();
			}

			// Wait for the delivery to occur...
			if (logger.isDebugEnabled()) logger.debug("Waiting for message to be delivered to the endpoint...");
			boolean workDone = latch.await(timeout, TimeUnit.MILLISECONDS);
			if (logger.isDebugEnabled()) logger.debug((workDone) ? "Message delivered, continue..." : "No message delivered, timeout occurred!");

			// Raise a fault if the test timed out
			assertTrue("Test timed out. It took more than " + timeout + " milliseconds. If this error occurs the test probably needs a longer time out (on your computer/network)", workDone);

		} catch (Exception e) {
			e.printStackTrace();
			fail("An unexpected error occurred: " + e.getMessage());

		} finally {
			// Always remove the listener if created
			if (listener != null) muleContext.getNotificationManager().removeListener(listener);
		}
		
		return receivedMessageHolder.value;		
    }

	/**
	 * Sends the payload and headers to the inboundEndpointAddress and waits timeout ms for a MuleMessage to be processed by a service component with the name serviceComponentName. 
	 * 
	 * Sample usage:
	 * 
	 *	Map props = new HashMap();
	 *	String message            = "Annn";
     *  String expectedResult     = "1nnn";
     *  String receivingService   = "some-teststub-service";
	 *	int    timeout            = 5000;
	 *
	 *	// Setup inbound endpoint for jms
	 *	String inboundEndpoint = "jms://" + IN_QUEUE;
	 *
	 *	// Invoke the service and wait for the transformed message to arrive at the receiving teststub service
	 *	MuleMessage reply = dispatchAndWaitForServiceComponent(inboundEndpoint, message, props, receivingService, timeout);
	 *	String transformedMessage = reply.getPayload().toString();
	 *
	 *	// Verify the result, i.e. the transformed message
     *   assertEquals(expectedResult, transformedMessage);
	 * 
	 * 
	 * @param inboundEndpointAddress
	 * @param payload
	 * @param headers
	 * @param serviceComponentName
	 * @param timeout in ms
	 * @return the received MuleMEssage on the outboundEndpoint
	 */
	protected MuleMessage dispatchAndWaitForServiceComponent(String inboundEndpointAddress, Object payload, Map headers, final String serviceComponentName, long timeout) {
		return dispatchAndWaitForServiceComponent(new DispatcherMuleClientImpl(muleContext, inboundEndpointAddress, payload, headers), serviceComponentName, timeout);
    }

    /**
     * Helper method that waits for an exception to be throwed
     *
     * @param timeout
     * @return
     */
    protected Exception waitForException(long timeout) {
    	return dispatchAndWaitForException(null, null, null, timeout);
    }

    /**
     * Helper method for initiating a test and wait for an exception to be throwed
     *
     * @param inboundEndpointAddress
     * @param payload
     * @param headers
     * @param timeout
     * @return
     */
    protected Exception dispatchAndWaitForException(String inboundEndpointAddress, Object payload, Map headers, long timeout) {
		// Declare MuleMessage to return
		final ValueHolder exceptionHolder = new ValueHolder();

    	// Declare countdown latch and listener
		final CountDownLatch latch = new CountDownLatch(1);
		ExceptionNotificationListener listener = null;
		MuleClient muleClient = null;

		try {
			// First create a muleClient instance
			muleClient = new MuleClient(muleContext);

			// Next create a listener that listens for exception on the connector
			listener = new ExceptionNotificationListener() {
				public void onNotification(ServerNotification notification) {

					// Only care about ExceptionNotification
					if (notification instanceof ExceptionNotification) {
						ExceptionNotification exceptionNotification = (ExceptionNotification)notification;

						Throwable exception = (Throwable)exceptionNotification.getSource();
						int       action    = exceptionNotification.getAction();
						
						// If it is a exception event then countdown the latch.
						if (action == EXCEPTION_ACTION ) {
							if (logger.isDebugEnabled()) logger.debug("Expected exception occurred: " + exception.getMessage() + ", time to countdown the latch");
							exceptionHolder.value = exception;
							latch.countDown();
							
						} else {
							if (logger.isDebugEnabled()) logger.debug("Unexpected exception-action: " + exceptionNotification.getActionName() + " , continue to wait for the exception...");							
						}
					}
				}
			};

			// Now register an exception-listener on the connector that expects to fail
			muleContext.getNotificationManager().addListener(listener);

			// Perform the actual dispatch if the inboundEndpointAddress is not null
			if (inboundEndpointAddress != null) {
				muleClient.dispatch(inboundEndpointAddress, payload, headers);
			}

			// Wait for the exception to occur...
			if (logger.isDebugEnabled()) logger.debug("Waiting for an exception to occur...");
			boolean workDone = latch.await(timeout, TimeUnit.MILLISECONDS);
			if (logger.isDebugEnabled()) logger.debug((workDone) ? "Exception occurred, continue..." : "No exception occurred, instead a timeout occurred!");

			// Raise a fault if the test timed out
			assertTrue("Test timed out. It took more than " + timeout + " milliseconds. If this error occurs the test probably needs a longer time out (on your computer/network)", workDone);

		} catch (Exception e) {
			e.printStackTrace();
			fail("An unexpected error occurred: " + e.getMessage());

		} finally {
			// Dispose muleClient
			muleClient.dispose();

			// Always reset the current listener
			if (listener != null) muleContext.getNotificationManager().removeListener(listener);
		}

		return (Exception)exceptionHolder.value;
    }

	/**
     * Helper method for initiating a test and wait for an exception to be throwed
     *
     * TODO: Only handles ServiceExceptions today, need probably to be able to handle ConnectorExceptions as see in the future...
     * TODO: Do we even need this variant of dispatchAndWaitForException()-method?
     * 
     * @param inboundEndpointAddress
     * @param payload
     * @param headers
     * @param serviceName
     * @param timeout
     * @return
     */
    protected Exception dispatchAndWaitForException(String inboundEndpointAddress, Object payload, Map headers, final String serviceName, long timeout) {
		// Declare MuleMessage to return
		final ValueHolder exceptionHolder = new ValueHolder();

    	// Declare countdown latch and listener
		final CountDownLatch latch = new CountDownLatch(1);
		ExceptionNotificationListener listener = null;
		MuleClient muleClient = null;

		try {
			// First create a muleClient instance
			muleClient = new MuleClient(muleContext);

			// Next create a listener that listens for exception on the connector
			listener = new ExceptionNotificationListener() {
				public void onNotification(ServerNotification notification) {

					if (logger.isDebugEnabled()) logger.debug("notification received on " + notification.getResourceIdentifier() + " (action: " + notification.getActionName() + ")");

					// Only care about ExceptionNotification
					// FIXME: Mule 3.1, no clue what we will get in case of exceptions...
					System.err.println("### AbstractTestCase.dispatchAndWaitForException(...) received an notification of type: " + notification.getClass().getName());
					if (notification instanceof ExceptionNotification) {
						ExceptionNotification exceptionNotification = (ExceptionNotification)notification;

						// Only handle ServiceExceptions
						// TODO: Should probably also need to be able to handle ConnectorExceptions
// FIXME: Mule 3.1, no clue what we will get in case of exceptions...
/* FIXME: Mule 3.1, STARTS HERE * /
						if (exceptionNotification.getSource() instanceof ServiceException) {
							ServiceException exception = (ServiceException)exceptionNotification.getSource();
							int    action  = exceptionNotification.getAction();
							String service = exception.getService().getName();
							
							// If it is a exception event on our component then countdown the latch.
							if (action == EXCEPTION_ACTION && service.equals(serviceName)) {
								if (logger.isDebugEnabled()) logger.debug("Expected exception occurred: " + exception.getMessage() + ", time to countdown the latch");
								exceptionHolder.value = exception;
								latch.countDown();
								
							} else {
								if (logger.isDebugEnabled()) logger.debug("Unexpected exception (" + exception.getMessage() + ") occurred on service: " + serviceName  + ", continue to wait for exception the right service...");							
							}
						}
/ * FIXME: Mule 3.1, ENDS HERE */
					}
				}
			};

			// Now register an exception-listener on the connector that expects to fail
			muleContext.getNotificationManager().addListener(listener);

			// Perform the actual dispatch
			muleClient.dispatch(inboundEndpointAddress, payload, headers);

			// Wait for the exception to occur...
			if (logger.isDebugEnabled()) logger.debug("Waiting for an exception to occur...");
			boolean workDone = latch.await(timeout, TimeUnit.MILLISECONDS);
			if (logger.isDebugEnabled()) logger.debug((workDone) ? "Exception occurred, continue..." : "No exception occurred, instead a timeout occurred!");

			// Raise a fault if the test timed out
			assertTrue("Test timed out. It took more than " + timeout + " milliseconds. If this error occurs the test probably needs a longer time out (on your computer/network)", workDone);

		} catch (Exception e) {
			e.printStackTrace();
			fail("An unexpected error occurred: " + e.getMessage());

		} finally {
			// Dispose muleClient
			muleClient.dispose();

			// Always reset the current listener
			if (listener != null) muleContext.getNotificationManager().removeListener(listener);
		}

		return (Exception)exceptionHolder.value;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy