Adsense

November 14, 2019

Comparing JSON string payload to another JSON string - Mule4

In REST API Mule development in which system returns a JSON response, it is always advisable to write MUnit tests and assert the entire JSON response payload to avoid contract conflicts/mismatches.


Objective:

Our objective is loading expected JSON data from a file and comparing it with actual MUnit payload which we got from the tested flow.

Problem Description:

If You are using Mule 4 and seeing MUnit test fails comparing JSON string payload to another JSON string.
The application produces an output similar to below:
%dw 2.0
output application/json
---
{
  message: "Success PUT"
}

The sample payload below to compare for the MUnit test is saved in a file:
{"message":"Success PUT"}

After running your MUnit you may get similar error like below:

java.lang.AssertionError: The response payload is not correct! at file: [munit-for-apikit-flow-part2-mule4-apikit-test.xml], line: [22]
Expected: "{\"message\":\"Success PUT\"}" as String {class: "java.lang.String"}
     but: "{\n  \"message\": \"Success PUT\"\n}" as String {encoding: "UTF-8", mediaType: "application/java; charset=UTF-8", mimeType: "application/java", class: "java.lang.String", contentLength: 30} at (root)

at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)



Problem Solution:

Use "readUrl" function to compare both types as JSON with JSON:

<munit-tools:assert-that expression="#[%dw 2.0 output application/json ---payload]" is='#[MunitTools::equalTo(readUrl("classpath://scaffolder/response/put_201_apikit-put_application_json.json", "application/json"))]' message="The response payload is not correct!" doc:name="Assert That - Payload is Expected" doc:id="bb6653e2-3022-4644-9099-204d13a5fce6"/>
   

Please find sample Mule project in Github munit-for-apikit-flow-part1-mule4

Happy Learning :)
Read More »

November 10, 2019

MUnit coverage for APIKit flows Part1 - Mule4

In my last article How to generate Mule flow using RAML.
Now here in this article we will see how to write MUnit test cases for flows that were created with APIkit RAML.

Application takes a RAML file and maps it to an implementation of an API in Mule.


We will see the implementation routes that handles incoming request based on Http methods (GET, POST, PUT, DELETE) and URL using MUnit.


Now let's start writing MUnits for routing flows:



Step 1: Generate Munit Flow from Apikit Flow: 


Right click on APIKit router-->Create Test Suite for Munit

create-munit-flows


Step 2: Run MUnit Suite:

Right click Munit flow--> select Run MUnit suite

run-munit-suite


Step 3: Flow execution sequence

Please check your MUnit test configuration if your MUnit is not behaving properly. Enable flow sources must be configured to List of Flows section as shown below:
enable-munit-flow

Then MUnit will find the source and will execute the test accordingly.

normal-flow-execution-sequence

Step 4: Coverage report:

munit-coverage-studio-report


Please find sample Mule project in Github munit-for-apikit-flow-part1-mule4

After running MUnit you will get MUnit coverage report like shown above. But If you have noticed APIKit main flow is having very less coverage percentage and it only covers resource flows. So, how we can increase or get the MUnit coverage for APIKit main flow which includes exception handling processors?
error-flow-execution-sequence

For this you needed to write MUnit additionally to cover these scenario which I will explain in my next article.

Happy Learning :)
Read More »

November 05, 2019

Create APIKit project using raml-Mule4

In this article we will see how we can create or generate Mule 4 project using RAML.
We will also see how Mule flow responds in case of Success and Validation scenarios.

RAML stands for RESTful API Modeling Language

RAML (Rest API Modeling Language) is based on YAML format, which is used to design REST APIs. RAML provides various features, including standardization, re-usability, easy readability, and much more. RAML provides a structure to the API which is useful for developers to start development process and it also helps clients to understands the request and response structure outcomes before hand.

What RAML contains?

  • Endpoint URL with its Query parameters and URI parameters,
  • HTTP methods to which API is listening to (GET, POST, PUT, DELETE),
  • Request and response schema and sample message,
  • HTTP response code that an API will return (eg: 200, 400, 404, 415, 500).

Lets jump into code build:

Step 1: Download a sample RAML file link

Step 2: Create Mule project: From AnypointStudio
             GoTo File--> New --> Mule Project
  • Provide Project Name
  • Select Runtime
  • Import RAML file by specifying file location or URL
  • Click finish button

import-raml-anypointstudio


Step 3: Building and Running Mule Project

Right click on the project --> Run As --> Mule Application


run-mule-app


Step 4: Test your deployed App through API Console


API-console

Step 5: Check Success Scenario

Success Test through API console

Flow execution sequence in Success Scenario
In API console, When we click on "GET"
  • Request will be sent to HTTP listener endpoint.
  • HTTP listener takes the request and forwards to APIKit router
  • APIKit validates the incoming requests and passes it to designated flow.
  • Here it is passing to "get:\apikit-login:apikit-raml-flow-Mule4-config" flow
  • Request is processed and gives a 200 OK response.
Success response flow



Step 6: Check Error Scenario

Error Test through API console

Flow execution sequence in Error Scenario(Bad Request)
On Api Console, When we execute DELETE operation.
  • Enter incorrect value in Delete Id.
  • Request will receive to HTTP endpoint and forwards to APIKit router.
  • APIKit router validates the incoming request.
  • On validation failed APIKit throws an error and which is caught by error handler.
  • Error handler passes the flow execution to APIKIT:BAD_REQUEST scope and gives response with  status code 400
Error response flow

Below are some error codes and their meanings which we normally uses in our development.
HTTP Error Code List Description

Please find sample Mule project in Github raml-apikit-flow-mule4

Next article we will see how to write MUnit test cases for these APIKit flows - Part 1


Read More »

October 31, 2019

Running MUnit for single file flow and Tags-Mule4

In this Article we will see how to run single munit at a time through command line and from Anypoint studio.

Also we will see how to run MUnits using Tags from command line


Execute from Command Line

Using "mvn test" at the terminal will test all MUnit tests, but here we describe how to test only one MUnit file

Run the following command at the project root folder.


In the following example, the MUnit test file is called run-single-munit-test-suite.xml


mvn clean test -Dmunit.test=run-single-munit-test-suite.xml



Running Single MUnit test case

XML file contains several tests, you may add the test name like this:

mvn clean test -Dmunit.test=abc.xml#testName

mvn clean test -Dmunit.test=mvn clean test -Dmunit.test=run-single-munit-test-suite.xml#run-single-munit-test-suite-run-single-munitFlowTest
  
In this case, the "testName" is the name of the test to be executed.


Execute from AnypointStudio

Right click in Munit file --> Run MUnit suite
Run MUnit suite


Right click on test Name--> Run MUnit test
Run MUnit test


Running Munit using Tags CommandLine

Tags are important to categorize the MUnits that needs to be executed based on the requirement. It is more like developer friendly to execute the different test scenarios.

Munit Tags

mvn clean test -Dmunit.tags=flow

Above command will run all the munit tests tagged as name "flow"

You can also use combination as below:

mvn clean test -Dmunit.test=run-single-munit-test-suite.xml -Dmunit.tags=flow

Please find sample Mule project in Github run-single-munit-Mule4

Happy learning :)

Read More »

October 26, 2019

Munit Issue with Async block inside subflow Mule4 - Resolved

In this article We will see the issue related while running Munit with Async block inside sub-flows. We will also see why this error normally occurs while running Munit and what are the options to resolve it.

java.lang.IllegalStateException: Couldn't register an instance of a MessageProcessorChain
at org.mule.runtime.config.internal.LazyMuleArtifactContext.lambda$createBeans$20(LazyMuleArtifactContext.java:399)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.mule.runtime.config.internal.LazyMuleArtifactContext.createBeans(LazyMuleArtifactContext.java:386)
Caused by: org.mule.runtime.core.privileged.registry.RegistrationException: Could not register object for key mule-munit-async-subflow-issueSub_Flow@729342238
Caused by: org.mule.runtime.api.lifecycle.LifecycleException: Failed to invoke lifecycle phase "start" on object: SubFlowMessageProcessorChain 'mule-munit-async-subflow-issueSub_Flow' 
  com.mulesoft.mule.runtime.core.internal.processor.TransformMessageProcessor@534ae04a, 
  org.mule.runtime.core.internal.processor.AsyncDelegateMessageProcessor@41cc2f00
]
Caused by: java.lang.NullPointerException
at org.mule.runtime.core.internal.component.ComponentUtils.getFromAnnotatedObject(ComponentUtils.java:37)

Problem Analysis:

As we know sub-flow is synchronous and single threaded in nature. Also Async block every time creates a new thread from running thread to complete the tasks in Async mode. So, in sub-flow scope it should never allow to create a separate thread from the running thread.

async,subflow

Resolution:

Method I: Change sub-flow to private flow
By changing the sub-flow to private flow, you can resolves this issue. As flow supports multi thread execution. So when Async block will called a new thread will be created and registered to its main thread and finishes its execution in Async mode.

async,flow




Method II: Add Try scope on Async scope

Second method is to add Try block on top of Async block to make the execution transactional or running in single thread. So when Munit starts running it will execute and finish its tasks without any issue. 
 async, try, subflow

Which one to choose?

It all depends on your requirement and design. Normally adding try block in sub-flows is a better option if you don't want to change your existing design.


Happy Learning :)
Read More »