Contact Us 1-800-596-4880

Functional Testing

Because Mule is light-weight and embeddable, it is easy to run a Mule Server inside a test case. Mule provides an abstract JUnit test case called org.mule.tck.junit4.FunctionalTestCase that runs Mule inside a test case and manages the lifecycle of the server. The org.mule.tck.functional package contains a number of supporting classes for functionally testing Mule code, including FunctionalTestComponent. These classes are described in more detail in the following sections.

FunctionalTestCase

FunctionalTestCase is a base test case for Mule functional tests. Your test cases can extend FunctionalTestCase to use its functionality.

FunctionalTestCase fires up a Mule server using a configuration you specify by overriding the getConfigResources():

protected String getConfigResources()
{
	return "mule-conf.xml";
}
You can use the method getConfigResources to specify a configuration file or comma-separated list of configuration files to use. All configuration files must exist in your classpath.

You then create tests that interact with the Mule server. FunctionalTestCase extends junit.framework.TestCase, so JUnit is the framework for creating and running your test cases. For example, this simple test would send a message to a vm endpoint.

public void testSend() throws Exception {
	MuleClient client = new MuleClient(muleContext);
	String payload = "foo";
	Map<String, Object> properties = null;
	MuleMessage result = client.send("vm://test", payload, properties);
	assertEquals("foo Received", result.getPayloadAsString());
}

Notice the use of MuleClient to interact with the running Mule server. MuleClient is used to send messages to and receive messages from endpoints you specify in your Mule configuration file (mule-conf.xml in this case). The example mule-conf.xml file used in this example is shown below:

<?xml version="1.0" encoding="UTF-8"?><mule xmlns="http://www.mulesoft.org/schema/mule/core"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:spring="http://www.springframework.org/schema/beans"
 xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
 xmlns:test="http://www.mulesoft.org/schema/mule/test"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
 http://www.mulesoft.org/schema/mule/core
 http://www.mulesoft.org/schema/mule/core/current/mule.xsd
 http://www.mulesoft.org/schema/mule/vm
 http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
 http://www.mulesoft.org/schema/mule/test
 http://www.mulesoft.org/schema/mule/test/current/mule-test.xsd">
 <model name="TestComponentModel">
<service name="TestComponentService">
<inbound><inbound-endpoint address="vm://test"/></inbound>
<test:component appendString=" Received"/>
</service>
</model>
</mule>

Watchdog Timeout

The base test case class includes a watchdog timeout feature that times out your functional test after 60 seconds. To change this setting, add -Dmule.test.timeoutSecs=XX either to the mvn command you use to run Mule or to the JUnit test runner in your IDE. As of Mule 3.0-M2 you can also set the environment variable MULE_TEST_TIMEOUTSECS. If both the system property and the environment variable are set, the system property takes precedence.

FunctionalTestComponent

The previous example of FunctionalTestCase covers many common (synchronous) test scenarios, where the service responds directly to the caller. FunctionalTestComponent can help support richer tests, such as:

  1. Simulating asynchronous communication

  2. Returning mock data to the caller

  3. Common scenarios such as forced exceptions, storing message history, appending text to responses, and delayed responses.

The component includes two methods: the onCall method and the onReceive method that basically do the same thing.

  • onCall: receives a MuleEventContext as input and returns an Object.

  • onReceive: receives an Object as input and returns an Object.

In both methods, FunctionalTestComponent takes the message that is passed to it (either from the MuleEventContext or from the Object) and transform it into a String. It then creates a message and sends it back to the caller. It also checks whether any of its properties are set and acts accordingly.

Asynchronous Tests with FunctionalTestComponent

The FunctionalTestComponent supports two event mechanisms for responding to a caller asynchronously: event callbacks and notifications. Both event callbacks and notifications fire events that get handled by registered listeners. During functional testing, the listener will typically be a class accessible in the FunctionalTestCase.

Event Callbacks

User-defined event callbacks get called when the test component is invoked. Following is an example of a test case and Mule configuration that uses callbacks:

public void testEventCallback() throws Exception {
	EventCallback callback = new EventCallback() {
		public void eventReceived(MuleEventContext context, Object component) throws Exception {
			System.out.println("Thanks for calling me back");
		}
	};
	getFunctionalTestComponent("TestComponentService").setEventCallback(callback);
	MuleClient client = new MuleClient();
	client.send("vm://test", new DefaultMuleMessage("foo"));
}

In this example, the eventReceived callback method is invoked as soon as the FunctionalTestComponent receives the message, and a message is printed to the console. Test assertions could be made in this method.

The corresponding Mule configuration used in this example is as follows:

<?xml version="1.0" encoding="UTF-8"?><mule xmlns="http://www.mulesoft.org/schema/mule/core"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:test="http://www.mulesoft.org/schema/mule/test"
xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-current.xsd
 http://www.mulesoft.org/schema/mule/core
 http://www.mulesoft.org/schema/mule/core/current/mule.xsd
 http://www.mulesoft.org/schema/mule/vm
 http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
 http://www.mulesoft.org/schema/mule/test
 http://www.mulesoft.org/schema/mule/test/current/mule-test.xsd">
 <model name="TestComponentModel">
 <service name="TestComponentService">
 <inbound><inbound-endpoint address="vm://test"/></inbound>
 <component><singleton-object class="org.mule.tck.functional.FunctionalTestComponent"/></component>
 </service>
 </model>
 </mule>

Notice that in this configuration, we did not use the "<test:component>" element, since we need FunctionalTestComponent to be singleton for the callback to work properly.

For an example of an event callback on a Spring component, see the additional example below.

Notifications

Notifications are an alternative to event callbacks. When an event is received, the FunctionalTestComponent fires a notification informing us that the event has been received. It is up to us to set up a listener (the FunctionalTestNotificationListener) on our test to capture this notification.

To do this, we must first make our test case implement the FunctionalTestNotificationListener interface. Then, we must implement the method exposed by this listener, which is onNotification. In the example below, we check notification.getAction to see whether it is the FunctionalTestNotification fired by the FunctionalTestComponent. If it is, we print it out to the console.

public void onNotification(ServerNotification notification) {
	if (notification.getAction() == FunctionalTestNotification.EVENT_RECEIVED) {
	System.out.println("Event Received");
	}
}

For our listener to start listening for notifications, we must register it:

muleContext.registerListener(this,"myComponent");

Returning Mock Data from FunctionalTestComponent

FunctionalTestComponent can return mock data specified either in a file or embedded in the Mule configuration. For example, to have the FunctionalTestComponent return the message "donkey", you would configure the component as follows:

<test:component><test:return-data>donkey</test:return-data></test:component>

To return contents from a file, you could use:

<test:component><test:return-data file="abc.txt"/></test:component>

The file referenced should exist on the Mule classpath.

Other Useful Features of FunctionalTestComponent

Forcing Exceptions

You can use throwException to always return the exception specified by exceptionToThrow, as follows:

<test:component  throwException="true"  exceptionToThrow="your.service.exception"/>

Storing Message History

By default, every message that is received by the FunctionalTestComponent is stored and can be retrieved. If you do not want this information stored, you can set enableMessageHistory to false. For example, if you are running millions of messages through the component, an out-of-memory error would probably occur eventually if this feature were enabled.

To enable:

<test:component enableMessageHistory="true" />

Messages are stored in an ArrayList. To retrieve a stored message, you use the getReceivedMessage method to retrieve it by number (for example, getReceivedMessage(1) to retrieve the first message stored), or use getLastReceivedMessage to retrieve the last message that was received. You can use getReceivedMessages to return the total number of messages stored.

Appending Text to Responses

You can use appendString to append text to the response message, as follows:

<test:component appendString="Received" />

Delayed Responses

You can set waitTime to delay responses from this FunctionalTestComponent. In this example, responses are delayed five seconds:

<test:component waitTime="5000" />

Disable Inbound Transformer

You can set doInboundTransform to false to disable the inbound transformer. For example:

<test:component doInboundTransform="false" />

Additional Features

The functional package includes several additional classes, such as CounterCallback, a test callback that counts the number of messages received. For complete information, see the org.mule.tck.functional JavaDoc.

Additional Example: Event Callback With a Spring Component

This example is similar to the "Event Callbacks" example above, except the component used here is a Spring component. In this case, we can look up the component using the Spring registry.

public void testEventCallback() throws Exception {
	EventCallback callback = new EventCallback()    {
			public void eventReceived(MuleEventContext context, Object component)
			throws Exception {
			System.out.println("Thanks for calling me back");
			}
	};
	ApplicationContext ac = (ApplicationContext)muleContext.getRegistry().lookupObject(SpringRegistry.SPRING_APPLICATION_CONTEXT);
	FunctionalTestComponent testComponent = (FunctionalTestComponent) ac.getBean("FTC");
	testComponent.setEventCallback(callback);
	MuleClient client = new MuleClient();
	client.send("vm://test", new DefaultMuleMessage("foo"));
}

The corresponding Mule configuration would be as follows:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:test="http://www.mulesoft.org/schema/mule/test"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core
http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/vm
http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/test
http://www.mulesoft.org/schema/mule/test/current/mule-test.xsd">
<spring:bean id="FTC" class="org.mule.tck.functional.FunctionalTestComponent" />
<model name="TestComponentModel">
<service name="TestComponentService">
<inbound><inbound-endpoint address="vm://test" /></inbound>
<component>
<spring-object bean="FTC" />
</component>
</service>
</model>
</mule>

Test Component Configuration Reference

The following is detailed information about the test components provided in the test framework (mule-test.xsd).

Component

A component that can be used for testing message flows. It is a configurable component. The return data for the component can be set so that users can simulate a call to a real service. This component can also track invocation history and fire notifications when messages are received.

Attributes of <component…​>

Attribute Description

throwException

Whether the component should throw an exception before any processing takes place.

Type: boolean
Required: no
Default: none

logMessageDetails

Whether to output all message details to the log. This includes all headers and the full payload. The information will be logged at INFO level.

Type: boolean
Required: no
Default: none

doInboundTransform

Whether the message is transformed using the transformer(s) set on the inbound endpoint before it gets processed. The default is true.

Type: boolean
Required: no
Default: true

exceptionToThrow

A fully-qualified classname of the exception object to throw. Used in conjunction with throwException. If this is not specified, a FunctionalTestException is thrown by default.

Type: name (no spaces)
Required: no
Default: none

exceptionText

The text of the exception that is thrown. Used in conjunction with throwException. If this is not specified, an empty message is used.

Type: string
Required: no
Default: none

enableMessageHistory

Every message that is received by the test component is stored and can be retrieved. If you do not want this information stored, such as if you are running millions of messages through the component, you can disable this feature to avoid a potential out of memory error.

Type: boolean
Required: no
Default: none

enableNotifications

Whether to fire a FunctionalTestNotification when a message is received by the component. Test cases can register to receive these notifications and make assertions on the current message.

Type: boolean
Required: no
Default: none

appendString

A string value that is appended to every message payload that passes through the component. Note that by setting this property you implicitly indicate that the message payload is converted to a string and that a string payload is returned. The inbound transformer (if any) gets applied first, but if that does not return a string, MuleEventContext.getMessageAsString() is called directly thereafter.

Type: string
Required: no
Default: none

waitTime

The time in milliseconds to wait before returning a result. All processing happens in the component before the wait begins.

Type: long
Required: no
Default: none

id

The name of this component.

Type: string
Required: no
Default: none

Child Elements of <component…​>

Name Cardinality Description

return-data

0..1

Defines the data to return from the service once it has been invoked. The return data can be located in a file, which you specify using the file attribute (specify a resource on the classpath or on disk), or the return data can be embeddded directly in the XML.

callback

0..1

A user-defined callback that is invoked when the test component is invoked. This can be useful for capturing information such as message counts. Use the class attribute to specify the callback class name, which must be an object that implements org.mule.tck.functional.EventCallback.

Web Service Component

A component that can be used for testing web services. This component has the same properties as component element, but in addition to implementing org.mule.api.lifecycle.Callable, it also implements org.mule.api.component.simple.EchoService, org.mule.tck.testmodels.services.DateService, and org.mule.tck.testmodels.services.PeopleService. When using this with WS endpoints such as CXF, be sure to set the serviceClass property of the endpoint to the type of service you are using.

Attributes of <web-service-component…​>

Attribute Description

throwException

Whether the component should throw an exception before any processing takes place.

Type: boolean
Required: no
Default: none

logMessageDetails

Whether to output all message details to the log. This includes all headers and the full payload. The information will be logged at INFO level.

Type: boolean
Required: no
Default: none

doInboundTransform

Whether the message is transformed using the transformer(s) set on the inbound endpoint before it gets processed. The default is true.

Type: boolean
Required: no
Default: true

exceptionToThrow

A fully-qualified classname of the exception object to throw. Used in conjunction with throwException. If this is not specified, a FunctionalTestException is thrown by default.

Type: name (no spaces)
Required: no
Default: none

exceptionText

The text of the exception that is thrown. Used in conjunction with throwException. If this is not specified, an empty message is used.

Type: string
Required: no
Default: none

enableMessageHistory

Every message that is received by the test component is stored and can be retrieved. If you do not want this information stored, such as if you are running millions of messages through the component, you can disable this feature to avoid a potential out of memory error.

Type: boolean
Required: no
Default: none

enableNotifications

Whether to fire a FunctionalTestNotification when a message is received by the component. Test cases can register to receive these notifications and make assertions on the current message.

Type: boolean
Required: no
Default: none

appendString

A string value that is appended to every message payload that passes through the component. Note that by setting this property you implicitly indicate that the message payload is converted to a string and that a string payload is returned. The inbound transformer (if any) gets applied first, but if that does not return a string, MuleEventContext.getMessageAsString() is called directly thereafter.

Type: string
Required: no
Default: none

waitTime

The time in milliseconds to wait before returning a result. All processing happens in the component before the wait begins.

Type: long
Required: no
Default: none

id

The name of this component.

Type: string
Required: no
Default: none

Child Elements of <web-service-component…​>

Name Cardinality Description

return-data

0..1

Defines the data to return from the service once it has been invoked. The return data can be located in a file, which you specify using the file attribute (specify a resource on the classpath or on disk), or the return data can be embeddded directly in the XML.

callback

0..1

A user-defined callback that is invoked when the test component is invoked. This can be useful for capturing information such as message counts. Use the class attribute to specify the callback class name, which must be an object that implements org.mule.tck.functional.EventCallback.