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

Mule and Mule Runtime: Part III

DZone's Guide to

Mule and Mule Runtime: Part III

Unit testing main flows is bit more complicated. Since our main flow has a flow reference, we need to mock the flow reference before we call the main flow.

· Integration Zone
Free Resource

Modernize your application architectures with microservices and APIs with best practices from this free virtual summit series. Brought to you in partnership with CA Technologies.

This is a continuation of my previous blogs about MUnit. You can view them here and here. This is the last part of blog about MUnit, so if you have not read previous parts yet, I highly recommend you to go through them before continuing. You can watch the video tutorials on YouTube here and here.

Let's get going with the remaining test cases.

Unit Test Case 3: main-flow-test-suite.xml 

Unit testing main flows is bit more complicated, because in a unit test case, we should only be testing the flow under test and not the flow reference to other flow — but since our main flow has a flow reference, what we need to do is use the MUnit mocking framework and mock the flow reference before we call the main flow. Once the mock object is ready, MUnit will replace the flow reference call with the mock object and test our flow.

By doing mocking we achieve the autonomous implementation for our unit test case and we can run our test case even if the flow reference is not available or in case the referenced flow is still not implemented.

Let’s see how to do that:

<?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:munit-demo.xml" />
    </spring:beans>
    <munit:test name="main-flow-test-suite-munit-demoFlowTest" description="Test">
        <mock:when messageProcessor="mule:set-payload" doc:name="Mock Set Payload">
            <mock:with-attributes>
                <mock:with-attribute name="doc:name" whereValue="#['Set Payload']" />
            </mock:with-attributes>
            <mock:then-return payload="#[]" />
        </mock:when>
        <mock:when doc:name="Mock Decision flow ref" messageProcessor="mule:flow">
            <mock:with-attributes>
                <mock:with-attribute name="name" whereValue="#['decisionFlow']" />
            </mock:with-attributes>
            <mock:then-return payload="#[]">
                <mock:invocation-properties>
                    <mock:invocation-property key="decisionVariable" value="#['decision1']" />
                </mock:invocation-properties>
            </mock:then-return>
        </mock:when>
        <flow-ref name="main-flow" doc:name="Flow-ref to munit-demoFlow" />
        <munit:assert-payload-equals message="oops, wrong message" expectedValue="#['Decision 1 was taken']" doc:name="Assert Payload" />
    </munit:test>
</mule>


Image title

In the above test case and image, you can see we have two mocking objects:

  1.  We are mocking the set-payload and setting an empty payload. We need to do this because the flow reference, i.e., decision flow, is expecting a payload for its execution. Before we mock the flow reference, we need to satisfy the input values for this flow.
  2. In the second mock object, we are mocking the flow, which is quite simple. We have given the whereValue attribute and put the name of  decisionFlow and told the mock framework that this name is the name of flow. Now, how does the framework knows that it has to mock a flow? It is done by the messageProcessor property. The object that we want to mock is mule:flow.
  3. Another important thing to notice is that we are also setting invocation-property before coming out of the flow mock. This is required because our main flow needs a flow variable named decisionVariable to take the decision and set the payload.

Again, I have left the implementation of second flow test for you to try.

Functional Test Case: functional-test-suite.xml 

The functional test is very simple in our case. Basically, in functional test cases, we will be testing the end-to-end flow of our application. Our flow starts from the HTTP endpoint, so we will not be calling HTTP endpoint. Instead, we will be calling a flow with its name as a flow reference and setting inbound-property decisionKey in http query params and doing two test cases to test both the outputs.

<?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: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">
    <munit:config name="munit" doc:name="MUnit configuration" />
    <spring:beans>
        <spring:import resource="classpath:munit-demo.xml" />
    </spring:beans>
    <munit:test name="main-flow-functional-test-suite" description="Test">
        <munit:set payload="#['']" doc:name="Set Message">
            <munit:inbound-properties>
                <munit:inbound-property key="http.query.params" value="#[['decisionKey':'value1']]" />
            </munit:inbound-properties>
        </munit:set>
        <flow-ref name="main-flow" doc:name="Flow-ref to main-flow" />
        <munit:assert-payload-equals message="Sorry wrong response" expectedValue="#['Decision 1 was taken']" doc:name="Assert Payload" />
    </munit:test>
</mule>

Image title

I think the code above is self-explanatory, so I will leave it up to you to understand.

You can view the video tutorial below.

With this, we come to end of our tutorial about MUnit. Let me know if it was of any help for you.

I hope you liked the blog. Please let me know your comments and suggestions.

The Integration Zone is proudly sponsored by CA Technologies. Learn from expert microservices and API presentations at the Modernizing Application Architectures Virtual Summit Series.

Topics:
mulesoft ,anypoint platform ,mule runtime ,unit testing ,integration

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}