import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class MyTestSuite extends FunctionalMunitSuite {
}
MUnit Tests with Java
MUnit allows you to test your configuration files both with Java and XML code. This guide explains how to use Java to configure your suites and create your tests. You can use MUnit to create tests, create assertions over messages, and to mock, spy, and verify your message processors.
Testing your configuration files with Java or XML is your choice. However, only XML currently allows testing with coverage, dynamic ports, and use of the Maven plugin. |
Creating Your Suite Class
To run MUnit tests with Java, create a class that extends FunctionalMunitSuite
.
For example:
Choosing a Configuration File to Test
To specify a configuration file you want to test, implement the
getConfigResources
method in your class and return the name of the
configuration file.
If you don’t override this method, MUnit obtains the configuration files
from the information specified in the mule-deploy.properties
file, or, if this file is not found,
from the mule-config.xml
file.
@Override
protected String getConfigResources() {
return "my-config-file.xml";
}
To test more than one configuration file, return each configuration file name separated with a comma (","). For example: |
Enabling and Disabling Inbound Endpoints
To enable or disable inbound endpoints, override the haveToDisableInboundEndpoints
method. For example, if you want to enable inbound endpoints, use:
@Override
protected boolean haveToDisableInboundEndpoints() {
return false;
}
If you don’t override this method, MUnit by default disables inbound endpoints.
Enabling Inbound Endpoints for Flows
To only enable inbound endpoints for flows, override the
getFlowsExcludedOfInboundDisabling
method.
For example:
@Override
protected List<String> getFlowsExcludedOfInboundDisabling() {
return Arrays.asList("firstFlow","thirdFlow");
}
If you don’t override this method, all flows start with their inbound endpoints disabled.
Enabling and Disabling Mocking for Mule Connectors
Enabling and disabling mocking in connectors only works with endpoint-based, outbound-endpoint connectors. |
To enable or disable mocking for a connector, override the
haveToMockMuleConnectors
method.
For example, if you don’t want to mock connectors, use:
@Override
protected boolean haveToMockMuleConnectors() {
return false;
}
If you don’t override this method, Mule connectors are mocked by default.
Actions When Creating and Starting the Mule Context
To perform actions when the Mule Context is created or started,
implement the muleContextStarted
or muleContextStarted
respectively.
For example, to print the Mule Context start date, use:
@Override
protected void muleContextStarted(MuleContext muleContext) {
System.out.println("Mule Context Started at" + new Date(muleContext.getStartDate()));
}
Creating Your Test
After you configure your suite, the next step is to create your tests. Create JUnit
tests
and use MUnit
to provide methods to test your configuration files.
The simplest way to create a test is with the @Test
annotation from JUnit
.
@Test
public void MyTest() {
}
Running a Flow
To test your configuration files, you should be able to run your flows.
The runFlow
method allows you to run a particular flow with a custom MuleEvent
as input,
and returns the resulting MuleEvent
.
To create a custom MuleEvent
for testing, MUnit
provides the testEvent
method that creates an event with an Object as payload.
For example, for the following flow:
<flow name="echoFlow">
<echo-component/>
</flow>
If you want to test that the payload is not modified after passing through an echo component, create this test:
import org.junit.Assert;
import org.junit.Test;
import org.mule.api.MuleEvent;
import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class MyTest extends FunctionalMunitSuite {
@Test
public void Test() throws Exception {
String myStringPayload = "myPayload";
MuleEvent resultMuleEvent = runFlow("echoFlow", testEvent(myStringPayload)); (1)
Assert.assertEquals(myStringPayload, resultMuleEvent.getMessage().getPayload()); (2)
}
}
1 | Run the echoFlow with a specific String as payload. |
2 | Assert that the resulting payload is the same as the original. |
MUnit does not provide its own assertions library for Java.
You can perform assertions using the JUnit assertions library,
as shown in the first line of the previous example.
|
Mocking
MUnit lets you define mocked behavior for a message processor. In this case, MUnit replaces the normal behavior of the message processor with the behavior you define.
Example Mocking Configuration
The following example sets up a flow for an HTTP connector to access a generic database
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:db="http://www.mulesoft.org/schema/mule/db" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<db:generic-config name="Generic_Database_Configuration" url="localhost:8082" doc:name="Generic Database Configuration"/>
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="myFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<db:select config-ref="Generic_Database_Configuration" doc:name="Select All Stocks">
<db:parameterized-query><![CDATA[SELECT * FROM flights;]]></db:parameterized-query>
</db:select>
<set-payload value="#[payload.substring(0,3)]" doc:name="Get Id"/>
</flow>
</mule>
Mocking Test
The following example tests for a sample payload:
import org.junit.Assert;
import org.junit.Test;
import org.mule.api.MuleEvent;
import org.mule.api.MuleMessage;
import org.mule.munit.common.mocking.MessageProcessorMocker;
import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class MyTestSuite extends FunctionalMunitSuite {
@Test
public void MockingTest() throws Exception {
String myMockPayload = "815-OA";
MuleMessage messageToBeReturned = muleMessageWithPayload(myMockPayload);
MessageProcessorMocker mocker = whenMessageProcessor("select").ofNamespace("db");
mocker.thenReturn(messageToBeReturned);
MuleEvent resultMuleEvent = runFlow("myFlow", testEvent("example"));
Assert.assertEquals("815", resultMuleEvent.getMessage().getPayload());
}
}
Using the When Message Processor
The whenMessageProcessor
method allows you to mock a message processor that matches
certain properties.
For example if the following flow is part of your configuration file:
<flow name="myFlow">
<set-payload value="#[1]" doc:name="Set One As Payload"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
There are several ways to match the processor you want to mock.
Add a Namespace Attribute
MessageProcessorMocker mocker =
whenMessageProcessor("set-payload").ofNamespace("mule");
Add Additional Attributes
In the example flow there is only one set-payload
message processor, but
if there were more than one, you should use other processor attributes, such as
the doc:name
attribute, to mock a message processor.
For example, for the following flow:
<flow name="myFlow">
<set-payload value="#[1]" doc:name="Set One"/>
<logger level="INFO" doc:name="Logger"/>
<set-payload value="#[2]" doc:name="Set Two"/>
</flow>
To mock only the second set-payload
processor, use:
MessageProcessorMocker mocker =
whenMessageProcessor("set-payload")
.withAttributes(Attribute.attribute("name").
ofNamespace("doc").
withValue("Set Two"));
Return Value
After you find a message processor that matches your attributes, you can return one or more of the following:
Method Name | Description | Example |
---|---|---|
|
Receives a Mule message to return by the message processor. |
|
|
Receives an exception that is thrown by the message processor. |
|
|
Returns the same event the message processor received. |
|
Example
This example builds on the last and shows you how to mock a message processor with Java:
<flow name="myFlow">
<set-payload value="My Current Payload"/>
<logger level="INFO"/>
</flow>
import org.junit.Test;
import org.junit.Assert;
import org.mule.api.MuleEvent;
import org.mule.munit.common.mocking.MessageProcessorMocker;
import org.mule.api.MuleMessage;
import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class MyTestSuite extends FunctionalMunitSuite {
@Test
public void test() throws Exception {
String myMockPayload = "myPayload"; (1)
MuleMessage messageToBeReturned =
muleMessageWithPayload(myMockPayload); (2)
MessageProcessorMocker mocker =
whenMessageProcessor("set-payload"); (3)
mocker.thenReturn(messageToBeReturned); (4)
MuleEvent resultMuleEvent =
runFlow("myFlow", testEvent("example")); (5)
Assert.assertEquals(myMockPayload,
resultMuleEvent.getMessage().getPayload()); (6)
}
}
1 | The payload that replaces the original. |
2 | The message returned by the mock. |
3 | The mock that matches the set-payload message processor. |
4 | Sets the return message to the mock. |
5 | Runs the flow with the custom MuleEvent . |
6 | Asserts that the mock payload replaces the original payload. |
Spy Message Processor
The spyMessageProcessor
method lets you create a spy so you can
see what happens before and after a message processor is called.
MunitSpy mySpy = spyMessageProcessor("logger");
The syntax that MunitSpy uses to match the message processor is the same
as the MessageProcessorMocker . Therefore, you can match a message processor
by name, namespace, and attributes.
|
Before and After Spy
To define the actions you want to perform before and after the message processor
executes, create classes that implement SpyProcess
and define the
spy
method.
For example:
SpyProcess beforeSpy = new SpyProcess() {
@Override
public void spy(MuleEvent event) throws MuleException {
System.out.println("Message before is " + event.getMessageAsString());
}
};
SpyProcess afterSpy = new SpyProcess() {
@Override
public void spy(MuleEvent event) throws MuleException {
System.out.println("Message after is " + event.getMessageAsString());
}
};
spyMessageProcessor("set-payload").before(beforeSpy).after(afterSpy);
Before and After Spy Example
The following example shows how to do assertions with the spy before and after a message processor executes.
<flow name="myFlow">
<logger level="INFO"/>
<set-payload value="#[2]"/>
</flow>
import org.junit.Assert;
import org.junit.Test;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.munit.common.mocking.SpyProcess;
import org.mule.munit.runner.functional.FunctionalMunitSuite;
@Test
public void SpyTest() throws Exception {
SpyProcess beforeSpy = new SpyProcess() { (1)
@Override
public void spy(MuleEvent event) throws MuleException {
Assert.assertEquals(1, event.getMessage().getPayload());
}
};
SpyProcess afterSpy = new SpyProcess() { (2)
@Override
public void spy(MuleEvent event) throws MuleException {
Assert.assertEquals(2, event.getMessage().getPayload());
}
};
spyMessageProcessor("set-payload") (3)
.ofNamespace("mule")
.before(beforeSpy)
.after(afterSpy);
runFlow("myFlow", testEvent(1)); (4)
}
1 | Create the spy process to be executed before the message processor. |
2 | Create the spy process to be executed after the message processor. |
3 | Create the spy message processor for the set payload, and add the before and after processes. |
4 | Run the flow with a custom MuleEvent . |
Verify Message Processor
For example, you can validate if a specific message processor has been called a specific number of times.
MunitVerifier verifier = verifyCallOfMessageProcessor("logger");
The syntax that MunitVerifier uses to match a message processor is the same
as the MessageProcessorMocker and MunitSpy . Therefore, you can match a
message processor by name, namespace, and attributes.
|
Verify Configuration and Test Examples
The following example uses a choice to determine how many times to call the logger:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<flow name="choiceFlow">
<choice>
<when expression="#[payload == 1]">
<set-payload value="Payload is 1" />
</when>
<otherwise>
<logger level="INFO" />
</otherwise>
</choice>
</flow>
</mule>
Verify Test Example
The following example tests the configuration:
import org.junit.Test;
import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class MyTestSuite extends FunctionalMunitSuite {
@Test
public void VerifyTest() throws Exception {
runFlow("choiceFlow", testEvent(1));
verifyCallOfMessageProcessor("set-payload").ofNamespace("mule").times(1);
}
}
Verify Times
MUnit provides the following methods that you can use to verify how many times to call a message processor.
Method Name | Description |
---|---|
|
Receives the exact number of times to call the message processor. |
|
Receives the minimum number of times to call the message processor. |
|
Receives the maximum number of times to call the message processor. |
|
The message processor must be called at least once. |
If the above conditions are not fulfilled, the test fails.
Example
The following example shows how to ensure that the logger
message processor is
called exactly three times.
<flow name="choiceFlow">
<choice>
<when expression="#[payload == 1]">
<logger level="INFO"/>
<logger level="INFO"/>
<logger level="INFO"/>
</when>
<otherwise>
<logger level="INFO"/>
</otherwise>
</choice>
</flow>
import org.junit.Test;
import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class MyTestSuite extends FunctionalMunitSuite {
@Test
public void VerifyTest() throws Exception{
runFlow("choiceFlow", testEvent(1)); (1)
verifyCallOfMessageProcessor("logger").ofNamespace("mule").times(3); (2)
}
}
1 | Run the flow with a custom MuleEvent. |
2 | Verify that the logger message processor is called three times. |