Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

MUnit Framework- Mule Unit Testing

DZone's Guide to

MUnit Framework- Mule Unit Testing

Learn how to use the MUnit framework to write automated unit testing test cases in MuleSoft for your integrations and APIs.

· Integration Zone ·
Free Resource

Ready for feedback: How would you use Capital One’s Virtual Card Numbers API?

Unit testing is the method by which individual units of source code can be tested to determine if they are fit for use. For Java programs, coders use the JUnit framework to write test cases. It fits into a CI/CD pipeline and tests your code before your build is deployed onto the server. 

Mulesoft has a framework called MUnit that allows you to write automated test cases for your integrations and APIs. It can be integrated with Maven and Surefire and is a perfect fit for your continuous deployment/integration environment.

Image titleMUnit Use Cases

  • Create your Mule test by writing Mule code
  • Create your Mule test by writing Java code
  • Disable flow inbound endpoints
  • Disable endpoint connectors
  • Mock outbound endpoints
  • Mock message processors
  • Spy any message processor
  • Verify message processor calls
  • Create not only unit tests but also integration tests in a local environment — MUnit allows you to start a local FTP/SFTP or DB server
  • Call the Mule client from Mule code
  • Assert flow exceptions
  • Enable or disable particular tests
  • See assertion/error reports with Mule stack trace
  • Extend the MUnit framework with plugins
  • Check visual coverage in Studio
  • Debug your tests with Studio

MUnit and Anypoint Studio

MUnit is integrated into Anypoint Studio that allows us to write, design, and run MUnit tests just like you run your Mule applications. 

Using MUnit in Anypoint Studio

MUnit is fully integrated with Anypoint Studio. You can use Studio’s graphical interface to:

  • Create and design MUnit tests
  • Run your tests
  • View test results and coverage
  • Debug your tests

The MUnit Folder

Using MUnit automatically adds a new folder, src/test/munit, to your project.

Let's Learn How to Write MUnit Test Cases

Creating a New MUnit Test in Studio

MUnit Studio integration is mainly built around XML-based tests. There are two basic ways to create a new MUnit test in Studio:

  • Choose a specific flow by right-clicking the flow and selecting MUnit.
  • Use the wizard, which allows you to create a test for any flow or application in the workspace.

Flows to Test

Let's start with a simple flow. In this flow, we are just setting a payload in response to an HTTP request. This is the flow we will be testing in this demo. My assumption is that you know how to write Mule flows, so I will not go into the details of writing a Mule flow.

Please use the Sample Code 1 block if you want to follow the steps to execute the MUnit test cases.

Image title

Sample Code 1:

<?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="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/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">

    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8095" doc:name="HTTP Listener Configuration"/>

    <flow name="exampleFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" allowedMethods="GET" doc:name="HTTP"/>


                   <set-payload value="#['payload_response_1']" doc:name="Set Response Payload"/>

    </flow>
</mule>


MUnit Test Case

To create a test for a specific flow, right-click the flow, then select MUnit > Create new suite.

Image title

It will create a test suite for you in the src/test/munit folder. For this simple use case, please add an Assert Payload to the MUnit test case.

Image title

Please replace your Munit code with Sample Code 2 for MUnit flow.

In Assert Payload, I am providing the expected value of the payload. Also, I am providing the test failure message which I would like to see on the dashboard if my test case fails.

Sample Code 2:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:mock="http://www.mulesoft.org/schema/mule/mock" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:munit="http://www.mulesoft.org/schema/mule/munit" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/munit http://www.mulesoft.org/schema/mule/munit/current/mule-munit.xsd
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/mock http://www.mulesoft.org/schema/mule/mock/current/mule-mock.xsd">
    <munit:config name="munit" doc:name="MUnit configuration"/>
    <spring:beans>
        <spring:import resource="classpath:munitdemo.xml"/>
    </spring:beans>
    <munit:test name="munitdemo-test-suite-exampleFlowTest" description="Test">
        <flow-ref name="exampleFlow" doc:name="Flow-ref to exampleFlow"/>
        <munit:assert-payload-equals expectedValue="#['payload_response_1']" doc:name="Assert Payload" message="oops, wrong payload!!!"/>
    </munit:test>
</mule>

Now, once you write the test case, you can run that test or you can run the entire test suite in case of multiple test cases.

Running a Test

To run a test, right-click the name of the test, then select Run MUnit Test.

Running a Test Suite

To run a test suite, right-click the empty canvas where the suite resides, then select Run MUnit suite.

Image title

Viewing Test Results

Studio displays MUnit test results in the MUnit tab of the left-hand explorer pane, outlined below:

Image title

The MUnit tab displays successful tests in green, failed tests in red.

The Coverage button in the image above allows you to see what flow the test covered, and the percentage of message processors in the flow that was covered by the test.

MUnit Test Coverage 

For this test case, we have 100% test coverage, as the MUnit test case covers the entire flow.

Image title

As this flow was very simple, let's add a choice router in the flow, which will route the flow to different payloads based on the value of a flow variable. Please use sample code 3 and update your configuration file with this.

Image title

Sample Code 3:

<?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="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/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">

    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8095" doc:name="HTTP Listener Configuration"/>

    <flow name="exampleFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" allowedMethods="GET" doc:name="HTTP"/>
        <set-variable variableName="my_variable" value="#['var_1']" doc:name="Variable"/>
        <choice doc:name="Choice">
            <when expression="flowVars['my_variable']=='var_1'">
                <set-payload value="#['payload_response_1']" doc:name="Set Response Payload"/>
            </when>
            <otherwise>
                <set-payload value="#['payload_response_2']" doc:name="Set Response Payload"/>
            </otherwise>
        </choice>

    </flow>
</mule>

Running the Test Suite

Just run the test suite again to check the coverage. To run the test suite, right-click the empty canvas where the suite resides, then select Run MUnit suite.

Image title

Viewing Test Results

Studio displays MUnit test results in the MUnit tab of the left-hand explorer pane, outlined below:

Image title

If you see, we just have 75% test coverage as the MUnit test case is not able to cover the second extra message processor which we have added in our Mule flow.

To achieve 100% test coverage, let's add another test case.

Now we are going to mock the data so that our MUnit test cases is able to mock the data, cover the entire flow and all message processors. We will mock the flow variable which is being set up in our sample code 3.

MUnit Test Case 1 With Mocked Data 

This is the first test case with mocked data. I am providing the code snippet for this test case for your reference.

Image title

MUnit Code snippet:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:mock="http://www.mulesoft.org/schema/mule/mock" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:munit="http://www.mulesoft.org/schema/mule/munit" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/munit http://www.mulesoft.org/schema/mule/munit/current/mule-munit.xsd
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/mock http://www.mulesoft.org/schema/mule/mock/current/mule-mock.xsd">
    <munit:config name="munit" doc:name="MUnit configuration"/>
    <spring:beans>
        <spring:import resource="classpath:munitdemo.xml"/>
    </spring:beans>
    <munit:test name="munitdemo-test-suite-exampleFlowTest" description="Test">
        <mock:when doc:name="Mock" messageProcessor="mule:set-variable">
            <mock:then-return payload="#[]">
                <mock:invocation-properties>
                    <mock:invocation-property key="my_variable" value="#['var_1']"/>
                </mock:invocation-properties>
            </mock:then-return>
        </mock:when>
        <flow-ref name="exampleFlow" doc:name="Flow-ref to exampleFlow"/>
        <munit:assert-payload-equals expectedValue="#['payload_response_1']" doc:name="Assert Payload" message="oops, wrong payload!!!"/>
    </munit:test>
</mule>

Running a Test Suite

To run the test suite, again right-click the empty canvas where the suite resides, then select Run MUnit suite.

Viewing Test Results

Studio displays MUnit test results in the MUnit tab of the left-hand explorer pane, outlined below:

Image title

In this case, we have 75% test coverage, as the MUnit test case is not able to cover the message processors. The reason is that we just mocked up the flow variable so that our flow can be tested for one payload.

We have to add another test case to cover the entire flow.

MUnit Test Case 2 With Mocked Data

This is the second test case with mocked data. I am providing the code snippet for this test case for your reference.

Image title

MUnit Code snippet for both test cases:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:mock="http://www.mulesoft.org/schema/mule/mock" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:munit="http://www.mulesoft.org/schema/mule/munit" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/munit http://www.mulesoft.org/schema/mule/munit/current/mule-munit.xsd
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/mock http://www.mulesoft.org/schema/mule/mock/current/mule-mock.xsd">
    <munit:config name="munit" doc:name="MUnit configuration"/>
    <spring:beans>
        <spring:import resource="classpath:munitdemo.xml"/>
    </spring:beans>
    <munit:test name="munitdemo-test-suite-exampleFlowTest" description="Test">
        <mock:when doc:name="Mock" messageProcessor="mule:set-variable">
            <mock:then-return payload="#[]">
                <mock:invocation-properties>
                    <mock:invocation-property key="my_variable" value="#['var_1']"/>
                </mock:invocation-properties>
            </mock:then-return>
        </mock:when>
        <flow-ref name="exampleFlow" doc:name="Flow-ref to exampleFlow"/>
        <munit:assert-payload-equals expectedValue="#['payload_response_1']" doc:name="Assert Payload" message="oops, wrong payload!!!"/>
    </munit:test>
     <munit:test name="munitdemo-test-suite-exampleFlowTest2" description="Test">
        <mock:when doc:name="Mock" messageProcessor="mule:set-variable">
            <mock:then-return payload="#[]">
                <mock:invocation-properties>
                    <mock:invocation-property key="my_variable" value="#['var_2']"/>
                </mock:invocation-properties>
            </mock:then-return>
        </mock:when>
        <flow-ref name="exampleFlow" doc:name="Flow-ref to exampleFlow"/>
        <munit:assert-payload-equals expectedValue="#['payload_response_2']" doc:name="Assert Payload" message="oops, wrong payload!!!"/>
    </munit:test>
</mule>

Running a Test Suite

To run this test suite, again right-click the empty canvas where the suite resides, then select Run MUnit suite.

Viewing Test Results

Studio displays MUnit test results in the MUnit tab of the left-hand explorer pane, outlined below:

Image title

Now we see that coverage is 100%. All message processors are marked as covered, as shown below.

Image title

Please see the coverage report for Application and Resources. You can get it by clicking on the Generate Report button under Coverage in MUnit tab.

MUnit Coverage Report

Application Coverage:

Image title

Resource Coverage:

Image title

I believe this will help Mule developers to learn the MUnit framework. Please share your feedback.

Learn how Capital One’s Virtual Card Numbers can benefit digital merchants and consumers.

Topics:
munit ,unit testing ,mulesoft ,integration ,devops ,ci/cd

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}