Mock APIKITRouter and writing MUnit test cases for different error types
- October 30, 2020
Whenever you write MUnit test cases for any flow, coverage is one of the upmost important components. However, due to error handling, it’s difficult to get the required coverage.
You have two options to meet the coverage threshold:
- Ignore the error handling flow
- Write test cases for error handling
This tech article has a detailed solution on writing test cases for error handling.
Ignoring the error handling flow
To ignore a flow, you can use the ignore plugins in the POM. So, when you execute the MUnit, that flow will be ignored, and you’ll get a better coverage report.
<plugins>
<plugin>
<groupId>com.mulesoft.munit.tools</groupId>
<artifactId>munit-maven-plugin</artifactId>
<configuration>
...
<coverage>
<ignoreFlows>
<ignoreFlow>flow-name</ignoreFlow>
</ignoreFlows>
</coverage>
...
</configuration>
</plugin>
</plugins>
But the MUnit Studio has a limitation with this approach: The coverage report doesn’t reflect this percentage. To get the exact coverage percentage, follow the report from the console or execute the test cases from the Command prompt.
Script for cmd execution:
mvn test or mvn clean test or mvn test -X
Writing test cases for error handling
To write a test case, you have a simple flow with one resource and one error handling block as APIKIT:BAD_REQUEST.
The transform message of the AKIKIT:BAD_REQUEST contains a payload with a message and a variable with httpStatus — you can have any custom message in the payload based on your requirements.
Now, you’ll write a test case for the main flow, which contains the error propagate block. It has a mock component as Behavior, a flow reference as an Execution step and an assert equal component in Validation.
The Flow reference refers to the main flow:
Next, configure the mock. Mock the APIKIT router and define the Error Typeid in the Error ta. Also, in the suite flow configuration, you need to define the expected error type. (These two steps are very important because, based on them, only the test case for error propagate will work).
Mock component
Flow configuration
For Assert That, the assertion can be based on the payload or httpStatus code. It completely depends on the user. This example uses httpStatus for validation.
Once all the configurations are done, the test flow is set up and you can execute the test case.
Console result
= Tests run: 1 - Failed: 0 - Errors: 0 - Skipped: 0 - Time elapsed: 0.18 sec
MUnit Studio result
MUnit coverage report
NOTE: Because we haven’t written any test case for the post:\demo resource flow, only for main flow, the coverage for the demo resource flow is 0% and the main flow is 100%.
Once the test case is executed, the part that comes under the success test execution — marked with a green check — indicates successful component test cases.
You can write similar test cases for other error types, as well.
Sample MUnit code
<?xml version="1.0" encoding="UTF-8"?>
<mule
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:munit="http://www.mulesoft.org/schema/mule/munit"
xmlns:munit-tools="http://www.mulesoft.org/schema/mule/munit-tools"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/munit http://www.mulesoft.org/schema/mule/munit/current/mule-munit.xsd
http://www.mulesoft.org/schema/mule/munit-tools http://www.mulesoft.org/schema/mule/munit-tools/current/mule-munit-tools.xsd">
<munit:config name="demo-test-suite.xml" />
<munit:test name="demo-test-suite-demo-main-BAD_REQUEST-Test" doc:id="8b6ba2d1-4696-43de-a07b-d854f4e5e2b6" description="Test" expectedErrorType="APIKIT:BAD_REQUEST">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when APIKIT:BAD_REQUEST" doc:id="6e68f7aa-75bf-4f15-93be-0c451375e9d9" processor="apikit:router">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="demo-config" attributeName="config-ref" />
</munit-tools:with-attributes>
<munit-tools:then-return >
<munit-tools:error typeId="APIKIT:BAD_REQUEST" />
</munit-tools:then-return>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow-ref to demo-main" doc:id="9df72122-506f-4759-aa24-134f8341b782" name="demo-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals doc:name="Assert equals" doc:id="93698feb-de93-40b2-bc11-44739ad55c00" actual="#[vars.httpStatus]" expected="#[400]"/>
</munit:validation>
</munit:test>
<munit:test name="demo-test-suite-demo-main-NOT_FOUND-Test" doc:id="8cfe733b-449f-4df1-b09d-06d79f63d8fb" description="Test" expectedErrorType="APIKIT:NOT_FOUND">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when APIKIT:NOT_FOUND" doc:id="ff561c10-4a97-456a-af92-29c144363d3d" processor="apikit:router">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="demo-config" attributeName="config-ref" />
</munit-tools:with-attributes>
<munit-tools:then-return >
<munit-tools:error typeId="APIKIT:NOT_FOUND" />
</munit-tools:then-return>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow Reference" doc:id="5079c1a2-74ff-4591-ac6d-840b8b15e78a" name="demo-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals doc:name="Assert equals" doc:id="596dd171-6c28-415b-8a9d-8b9152f62cb4" actual="#[vars.httpStatus]" expected="#[404]"/>
</munit:validation>
</munit:test>
<munit:test name="demo-test-suite-demo-main-METHOD_NOT_ALLOWED-Test" doc:id="635ace96-1503-40ce-8de3-13e7411726c8" description="Test" expectedErrorType="APIKIT:METHOD_NOT_ALLOWED">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when APIKIT:METHOD_NOT_ALLOWED" doc:id="894571a7-42b9-4caf-9be4-3c16d9cfa0f6" processor="apikit:router">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="demo-config" attributeName="config-ref" />
</munit-tools:with-attributes>
<munit-tools:then-return >
<munit-tools:error typeId="APIKIT:METHOD_NOT_ALLOWED" />
</munit-tools:then-return>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow-ref to demo-main" doc:id="b57e4856-e333-4b45-bb01-c234f8e5e9f9" name="demo-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals doc:name="Assert equals" doc:id="493307c6-825b-4652-a61e-2973332a972f" actual="#[vars.httpStatus]" expected="#[405]"/>
</munit:validation>
</munit:test>
<munit:test name="demo-test-suite-demo-main-NOT_ACCEPTABLE-Test" doc:id="1bec6f0d-01ed-43b2-bf39-8736cbf5e590" description="Test" expectedErrorType="APIKIT:NOT_ACCEPTABLE">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when APIKIT:NOT_ACCEPTABLE" doc:id="3a329baf-99df-49fb-8b18-636dc5316973" processor="apikit:router">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="demo-config" attributeName="config-ref" />
</munit-tools:with-attributes>
<munit-tools:then-return >
<munit-tools:error typeId="APIKIT:NOT_ACCEPTABLE" />
</munit-tools:then-return>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow Reference" doc:id="a46ee38a-13b0-431d-ab94-6fafa8492ee2" name="demo-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals doc:name="Assert equals" doc:id="35aff4f1-30e8-4cda-b71e-736d0b279a98" actual="#[vars.httpStatus]" expected="#[406]"/>
</munit:validation>
</munit:test>
<munit:test name="demo-test-suite-demo-main-UNSUPPORTED_MEDIA_TYPE-Test" doc:id="d8454189-e4e1-4375-b585-0a999a837619" description="Test" expectedErrorType="APIKIT:UNSUPPORTED_MEDIA_TYPE">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when APIKIT:UNSUPPORTED_MEDIA_TYPE" doc:id="f41c89d8-b712-47a4-b358-ef8cb3ba086c" processor="apikit:router">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="demo-config" attributeName="config-ref" />
</munit-tools:with-attributes>
<munit-tools:then-return >
<munit-tools:error typeId="APIKIT:UNSUPPORTED_MEDIA_TYPE" />
</munit-tools:then-return>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow-ref to demo-main" doc:id="92675038-645a-4a98-b897-06845a04e6e3" name="demo-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals doc:name="Assert equals" doc:id="5065fd21-8f7f-4d1f-a6d5-042f40aefbfd" actual="#[vars.httpStatus]" expected="#[415]"/>
</munit:validation>
</munit:test>
<munit:test name="demo-test-suite-demo-main-NOT_IMPLEMENTED-Test" doc:id="e2cbf56e-ee66-41cc-82be-333dd1eb292c" description="Test" expectedErrorType="APIKIT:NOT_IMPLEMENTED">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when APIKIT:NOT_IMPLEMENTED" doc:id="aeb6b8f2-7488-4608-b591-ee22331b85f0" processor="apikit:router">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="demo-config" attributeName="config-ref" />
</munit-tools:with-attributes>
<munit-tools:then-return >
<munit-tools:error typeId="APIKIT:NOT_IMPLEMENTED" />
</munit-tools:then-return>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow-ref to demo-main" doc:id="bd189bb8-d517-448c-bcdf-fe043190d0a0" name="demo-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals doc:name="Assert equals" doc:id="302886a9-6dc6-4c96-920f-0d6f4100aa9c" actual="#[vars.httpStatus]" expected="#[501]"/>
</munit:validation>
</munit:test>
</mule>
Happy learning!
— By Abhishek Bathwa