February 8 2016

The MuleSoft APIKit facilitates REST API implementation from RAML definitions. This toolkit is a framework with the ability to create Mule flows, mapped from the implementation of an API defined within a RAML (see APIKit Tutorial). Implementation of an API in this manner follows best practices, ensuring API-first development.

Developing tests for the flows generated by the APIKit can be done fairly easily using another framework available from MuleSoft, MUnit. This framework provides testing capabilities and is fully integrated with Maven, allowing for automated testing during the build process. It requires a plugin for Anypoint Studio.

There are two ways to test the flows generated by the APIKit. The first is by invoking flow references. The other is to test through the APIKit Router. The latter provides the ability to test the flows as they would be invoked during runtime, based on the RAML, which is the focus of this blog.

Test Suite Creation

To create a test suite for the APIKit flows, in Anypoint Studio right click the APIKit Router and select to create a test suite for RAML:

Create Test Suite

Once this is done, a test suite is generated that contains one flow for each resource/action/response code combination defined within the RAML (i.e. Employees/get/200, Employees/get/404). Since the same RAML was used to generate the API flows as well as the flows in the test suite, greater code coverage will be achieved.

Assertions

assertions

Along with automatic generation of the test flows, the MUnit test suite creation process also adds assertions within each of these flows that validates the returned http status and payload. The status returned from the invocation of the API flow is compared with an expected response code, as defined when the test flow was generated (resource/action/response code as mentioned above).

The other assertion that is generated automatically is one that compares the actual output returned from the API flow to an expected output. The expected output is generated during the test suite creation using the value specified for the example response (as shown in diagram above). If the example payload defined within your RAML is different then the intended expected results for a given test, a best practice is to define the expected results within an external file, stored in src/test/resources. Use the getResource function to read the file contents as shown below:

payload

XML:

<munit:assert-on-equals message="The response payload is not correct!" expectedValue="#[getResource('getEmployeeByIdExpectedResult.json').asString().replaceAll(&quot;\\s+&quot;,&quot;&quot;)]" actualValue="#[payload.replaceAll(&quot;\\s+&quot;,&quot;&quot;)]" doc:name="assert that - payload is as expected" />

Additional assertions can be added depending on the testing requirements.

Mocking

MUnit has mocking capabilities that ensure isolation of the test, where changes to external systems have no impact.  This is accomplished by creating mocks for endpoints or connectors defined within the API flow. One or more mocks can be added to the test flow, with each defining a mock payload response. Attributes can also be defined to specify the criteria for which the mock will used.

To add a mock to a test, drag a mock component to the test flow:

mocking

Within the mock element, choose a message processor that is intended to be mocked. This would be the external endpoint within the API flow for the given test scenario:

mock end point

XML:

<mock:when messageProcessor=".*:.*" doc:name="Mock"> <mock:with-attributes> <mock:with-attribute name="doc:name" whereValue="#['Get Google User']"/> </mock:with-attributes> <mock:then-return payload="#[getResource('getUserExpectedResult.json').asString()]"/> </mock:when>

The payload returned from the mock should reflect the Java type (i.e. String, Map, ArrayList, etc.) that the external endpoint being mocked returns.

Attributes can be added to further qualify the condition(s) for the mock. For example, the following defined attribute will cause the payload to be returned only if the input value, groupKey, is set to the value contained in Value:

mocking attribute

XML:<mock:with-attribute name="groupKey" whereValue="badaddress@gmail.com"/>

Gotchas

For flows that test an error response (i.e. Employees/get/404), a configuration is necessary to alleviate a testing error like “Response code 404 mapped as failure”. Add the status code value range within the HTTP advanced tab as shown below:

status values

XML:<http:success-status-code-validator values="0..599" />

Ensure the MUnit test suite configuration for the mock-connectors and mock-inbounds are both set to “false”:

Munit config

XML: <munit:config mock-connectors="false" mock-inbounds="false" />

You will know that these are set incorrectly if you receive the following error while invoking the test:

Flow endpoint is null, APIKIT requires a listener ref in each of it's flows

Running the Tests

Within Anypoint Studio, the test suite can be executed by right clicking on the test suite configuration file (i.e. api-apikit-test.xml) found in src/test/munit, select Run As->MUnit. The results of the test can be viewed within the MUnit tab:

munit studio

Running of these tests within Studio is beneficial during developing/refactoring of the tests, the real power comes during the build process in Maven. Because the framework is fully integrated with Maven, the tests are included in the build, run before the application is packaged. The build will fail if any of the MUnit tests fail, ensuring that only tested code is packaged for deployment, one of the tenets of Continuous Integration.

About the Author

Bio

Jennie has over 25 years of information technology experience, the majority of time spent in application integration. She has broad experience in integration architecture design and implementation utilizing several integration toolsets. As an architect, she has experience developing SOA/API Governance Framework and Reference Architectures.

Join the Conversation

Amit
May 16, 2016

hi, I am trying to do step 1 - > right click on APIkit Router -> Munit->create api.xml for RAML 

After this it gives me error "cannot create a new suite File for your Munit tests" on clicking OK

it actually create api.xml file but empty with no content.  Do we need any software update or any plugin to be installed seperately

bayapareddy
June 28, 2016

hi, I am trying to do step 1 - > right click on APIkit Router -> Munit->create api.xml for RAML 

After this it gives me error "cannot create a new suite File for your Munit tests" on clicking OK

it actually create api.xml file but empty with no content.  Do we need any software update or any plugin to be installed seper

Prakash
August 10, 2016

How to write munit for RAML validations pointing to HTTP - APIKIT component.

I tried but it throws validationException as expected but not able to catch it and make my munit passed it.

Enter your first name. It will only be used to display with your comment.
Enter your email. This will be used to validate you as a real user but will NOT be displayed with the comment.
By submitting this form, you accept the Mollom privacy policy.