Write MUnit to Validate API Integration (Mule 4)
This blog will help you reproduce downstream API behaviors w.r.t. HTTP error codes using MUnit without real-time integration with the process or system APIs.
Join the DZone community and get the full member experience.
Join For FreeDeveloping and designing new MUnit test cases for the same integration flow is an additional effort for the development and delivery team if any changes in the same integration flow come in the existing flows regarding request and response structures. To reduce such a repetitive approach in MuleSoft integrations, a configuration- and parameterized-based approach is introduced in the development.
This blog will help you reproduce downstream API behaviors w.r.t. HTTP error codes using MUnit without real-time integration with the process or system APIs. Developers or architects will not be required to design or develop a new MUnit flow if a new error code is added in future enhancement inflow.
What is MUnit?
MUnit is a Mule application testing framework that enables to formulate automated tests for mule integrations and API. MUnit is an integrated feature with Anypoint Studio and supports dependency tools like Maven.
With enhanced components, MUnits generates and verifies the expected behavior of integration flows. Furthermore, it plays a crucial role while working with API-led connectivity approaches or multi-layer integration platforms. As platform behavior changes with enhancement or required fixes for longer periods of platform existence, in such scenarios modifying or creating new MUnit test cases for the same integration flows will be an additional effort for the development team.
To overcome such scenarios, configuration-based MUnits will act as a reusable asset to reproduce and test the success level of new improved features of applications.
Configurable MUnits approach for API-led connectivity
To test unit and integration test cases for the API-led connectivity, we use MUnit components to produce scenarios of downstream APIs along with response structure to validate downstream APIs expected HTTP response status codes.
As MUnit facilitates and supports parameterized files as input for trigger events for MUnit test cases based on parameters configured in a configuration file. Prepare a YAML configurable file with required values and use it to configure it as parameterized property to generate events for the MUnit test case.
<munit:config name=“downstream-http-error-test.xml" >
<munit:parameterizations file="downstreamErrorCode.yaml" />
</munit:config>
Sample downstreamErrorCode.yaml file
Now design MUnit test cases to use the above parameterized file properties as input to execute and trigger events.
Set event created
In the below set-event component, variables will be assigned which were populated from the YAML property file, and will be used to prepare the both mocked HTTP-requester component and expected output as below.
For instance, in the below code snippet value assigned to expectedErrorCode variable from value populated from YAML file.
<munit:set-event doc:name="Set Event" >
<!-- Set event request payload -- >
<munit:payload value="#MunitTools::getResourceAsString('scaffolder/request/post_compliance_namescreening_application_json.json')]" mediaType="application/json" />
<!-- Set event request payload ENDS HERE-- >
<!-- Set event request header parameters -- >
<munit:attributes value="#[MunitTools::getResourceAsString('scaffolder/request/event-attributes.json')]" mediaType="application/json" />
<!-- Set event request header parameters ENDS HERE -- >
<!-- Set variables -- >
<munit:variables >
<munit:variable key="expectedErrorCode" value="${errorCode}" />
<munit:variable key="expectedHTTPStatus" value="${httpStatus}" />
<munit:variable key="expectedErrorMessage" value="${message}" />
<munit:variable key="expectedParentErrorMessage" value="${parentErrorMessage}" />
</munit:variables>
<!-- Set variables ENDS HERE -- >
</munit:set-event>
Mock HTTP-Requester Component
While mocking HTTP-requester components in the MUnit test case, we need to configure the “then-return” element of the mocking component and refer downstream-flow to throw HTTP errors with the support of mule flow to produce HTTP error codes scenarios and asserts payload which will be assigned in the on-error scope of integration flow.
Below flow will execute and populate variables for error codes.
test-mock-HTTP-call-downstream-error :
<munit:behavior >
<munit-tools:mock-when doc:name="Mock API Toolkit Returning Error" doc:id="######" processor="http:request" >
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="PAPI HTTP API Namescreening" attributeName="doc:name" />
</munit-tools:with-attributes>
<munit-tools:then-call flow="mock-http-call-downstream-error" />
</munit-tools:mock-when>
</munit:behavior>
Child flow to mock response
As the below flow triggers from the mocked component in the MUnit test case.
It will raise errors and use variables that are assigned in the set-event from the YAML configuration file to transform the expected payload in the HTTP error scenario.
test-mock-http-call-downstream-error
<flow name="test-mock-http-call-downstream-error" >
<http:request method="GET" doc:name="GET /mock Downstream Errors" path="/mocktest" configref="HTTP_Request_configuration">
<http:body >
<![CDATA[#[null]]]></http:body>
<http:headers >
<![CDATA[#[output application/java
---
{ "x-correlation-id" : correlationId }]]]></http:headers>
<http:query-params ><![CDATA[#[output application/java
---
{ "expectedStatusCode" : vars.expectedErrorCode,
"expectedHTTPStatus" : vars.expectedHTTPStatus,
"expectedErrorMessage" : vars.expectedErrorMessage
}]]]>
</http:query-params>
</http:request>
</flow>
Flow to raise http error
Below flow will receive an event triggered from flow ‘test-mock-http-call-downstream-error’ and raise an error by ‘Raise Error’ component and transform payload as expected for http error within ‘On error continue’ component.
<flow name="mock-http-call-downstream-error-response" >
<http:listener doc:name="Listener" path="/mocktest" config-ref="HTTP_Listener_config">
<http:response statusCode="#[vars.httpStatus default 200]" />
<http:error-response statusCode="#[vars.httpStatus default 500]" />
</http:listener>
<raise-error doc:name="Raise error: TEST:EXCEPTION" type="TEST:EXCEPTION"/>
<error-handler >
<on-error-continue enableNotifications="true" logException="true" doc:name="On Error Continue" type="TEST:EXCEPTION">
<ee:transform doc:name="Prepare Custom Error Response">
<ee:message><ee:set-payload resource="downStreamErrorTest/p-common-error-response.dwl" /></ee:message>
<ee:variables><ee:set-variable variableName="httpStatus">
<![CDATA[%dw 2.0
output application/java
---
attributes.queryParams.expectedHTTPStatus]]></ee:set-variable>
</ee:variables></ee:transform></on-error-continue></error-handler>
</flow>
Once the error message goes to the MUnit test case, it validates that if the error message is not empty then compare with an expected error message.
That's all for now!
Opinions expressed by DZone contributors are their own.
Comments