Contact Us 1-800-596-4880

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:

import org.mule.munit.runner.functional.FunctionalMunitSuite;

public class MyTestSuite extends FunctionalMunitSuite {

}

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: return "my-config-file.xml,my-second-config-file.xml"

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.

Match by Processor Name

MessageProcessorMocker mocker =
  whenMessageProcessor("set-payload");

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

thenReturn

Receives a Mule message to return by the message processor.

mocker.thenReturn(muleMessageWithPayload("myNewPayload"));

thenThrow

Receives an exception that is thrown by the message processor.

mocker.thenThrow(new IllegalArgumentException());

thenReturnSameEvent

Returns the same event the message processor received.

mocker.thenReturnSameEvent();

Example

This example builds on the last and shows you how to mock a message processor with Java:

Flow
<flow name="myFlow">
  <set-payload value="My Current Payload"/>
  <logger level="INFO"/>
</flow>
Test
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
<flow name="myFlow">
    <logger level="INFO"/>
    <set-payload value="#[2]"/>
</flow>
Test
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

times

Receives the exact number of times to call the message processor.

atLeast

Receives the minimum number of times to call the message processor.

atMost

Receives the maximum number of times to call the message processor.

atLeastOnce

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
<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>
Test
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.