Munit 2 - trying to test a simple GET endpoint by comparing response containing correlationId - mule

Using Mule 4 and have a GET endpoint : getEmployee
The API I am trying to MUNIT is an experience api and its expected response is :
{
"correlationId": correlationId ( Mule correlation id ),
"empDetails" : {
"ename": "John",
"eid": "100"
}
}
In the above response, data received from process api is set against empDetails.The experience api is adding correlationId in response.
The problem I am encountering is when trying to Munit this endpoint . I am mocking the process api response
So the mocked response is a static json file :
{
"ename": "John",
"eid": "100"
}
Once this mocked response ( from process api ) is received back in experience api , we append correlation id before sending response back.
So in My Munit I am trying to compare results from runtime with a static response from a json file.
My static response in json file is as below :
{
"correlationId": "abcd",
"empDetails" : {
"ename": "John",
"eid": "100"
}
}
Notice that above in static json file the correlation id is expected to be abcd
So in my munit I am trying to set correlation id with abcd :
<munit:set-event doc:name="Set Event">
<munit:attributes value="#[{ method : 'GET', requestPath: '/employee', headers : { 'X-
CORRELATION-ID' : 'abcd'}}]" />
...
...
However inspite of setting the correlationid header value to a fixed static value abcd , mule runtime is dynamically generating the value and as a result rather than having abcd in response we are getting a dynamic value causing munit to fail ...
Note - when I run the api and invoke this endpoint via postman , then whatever value i send in header X-Correlation-Id is being set against correlationid ( expected behaviour )
However in case of munit this is not happening .
I think the difference between the two is - in actual run - the HTTP listener is invoked Vs in case of Munit the specific flow is being tested ( after http listener and api kit router ) , so I am suspecting this is why mule is already setting correlation id in case of munit.
So really I need some way to control the value of correlationid in Munit , how do we achieve the same ?

Here are two ways to control the correlationId in your situation:
Use the Tracing module in the MUnit execution scope
<munit:execution>
<tracing:with-correlation-id correlationId='#["abcd"]'>
<!-- invoke flow here -->
</tracing-with-correlation-id>
</munit:execution>
Initiate the flow from your MUnit execution scope using the HTTP Requester and set the correlationId attribute to your intended value. Here you have to include both your APIKit main flow and your specific route flow in your enableFlowSources list for the MUnit test.

Related

Karate API -> JSON Request -> Base field in JSON not being sent in request (works in Postman)

My JSON request has a base value that is the top object.
Sample:
{
"partner_id": "6f4a3092-1b11-48c0-8a11-ae455b327ed8",
"borrowers": [
{
"loan": {
"loan_number": "89898989898222",
The partner_id is not being sent with the rest of the request.
Does this first object require special treatment to be sent with the rest of the request?
It feels like it should 'just work'
In my steps to file a bug, it started working in picking up the base object.

How to extract value from GET request in karate

I am new to REST and Karate testing. Our project uses Karate for service virtualization during integration tests. I am calling a RESTful GET API with the following url structure:
http://localhost:8080/SampleService/v1/person/{personId}/personAssetRelationships
Below is the Scenario I have written
#Scenario to get all assets a person was ever assigned
Scenario:
pathMatches(/SampleService/v1/person/{personId}/personAssetRelationships) &&
methodId('get')
* def responseStatus = 200
* def response =
"""
[
{
"personId": "13",
"assetIdentifier": "21324",
"assignedDate": "2020-11-22",
"returnedDate": "9999-12-31",
"replacedAssetIdentifier": null
}
]
"""
This works during my integration test. The only concern is that the personId in my response is static. I want to be able to use the personId that is passed in the request path in my response. I am not sure how a I can do that. Any suggestions would be helpful.
Thanks.
Won't pathParams.personId work, read the docs: https://github.com/intuit/karate/tree/master/karate-netty#pathparams
"personId": "#(pathParams.personId)",

How to get the current TraceId and SpanId

This article, https://devblogs.microsoft.com/aspnet/improvements-in-net-core-3-0-for-troubleshooting-and-monitoring-distributed-apps/, tells me that the field TraceId is available as a correlation id, which is great!
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
=> ConnectionId:0HLR1BR0PL1CH
=> RequestPath:/weatherforecastproxy
RequestId:0HLR1BR0PL1CH:00000001,
SpanId:|363a800a-4cf070ad93fe3bd8.,
TraceId:363a800a-4cf070ad93fe3bd8,
ParentId: Executed endpoint 'FrontEndApp.Controllers.WeatherForecastProxyController.Get
(FrontEndApp)'
In fact, I can see that in our log sink this works as advertised: When web application A serves a request and in doing so invokes web application B, both of them write the same TraceId value to the log.
As far as I understand, any ASP.NET Core application that receives an incoming Request-Id header will attach the same header to outgoing requests, but if the header does not exist on the incoming request, an new value will be generated for the outgoing request.
We have been asked to add that value to the response from web application A, but it is (not surprisingly) not available on the incoming request.
I have been looking at the System.Diagnostics.Activity class, but accessing Activity.Current isn't giving me an instance with anything useful - the TraceID is just {} - i.e. empty.
My question is this: How can I access the TraceId value in the context of a web application?
-S
I had the same problem when I tried to add a header with TraceId value.
Doing some tests with ModelValidation, I saw then in this kind of error response the "traceId" value was correct, but I couldn't obtain this value from http context variable in any way.
Then I went to net core source code to see DefaultProblemDetailsFactory implementation and surprise! The "traceId" value is obtained doing this:
var traceId = Activity.Current?.Id ?? httpContext?.TraceIdentifier;
Yes, you can get THE traceId using Activity static variable.
You can get tracid and spanid in dictionary.
using var subject = _tracer.BuildSpan($"Operation").StartActive();
var spanContext = subject.Span.Context;
var dictionary = new Dictionary<string, string>();
_tracer.Inject(spanContext, BuiltinFormats.TextMap, new TextMapInjectAdapter(dictionary));

Mule Merge HTTP response message

I am using MULE and 3 transformers, 2 that that require information from an HTTP response + a POJO. Transformer 2 and 3 only get the HTTP POST repsonse now and not the POJO.
Transformer1 gets a POJO and transforms it , sends it to a HTTP endpoint, it uses a Post request.
The response of the POST is used in transformer 2 and 3, however they
also need the POJO that to do their transformation !
How can I use the pojo that was used in Transformer 1 + the http response in transformer
2 and 3? I want a message to enter the ALL control flow with the payload = http response + the POJO.
Is it possible to add the two in a message e.g 2 payloads in 1 message ? How can I solve this issue?
Thanks in advance.
Mule Flow:
You can store the original POJO payload as a message property to access it later in the flow. See here for an introduction to the Mule message property scopes:
http://blogs.mulesoft.org/mule-school-the-mulemessage-property-scopes-and-variables/

IBM Worklight filter HTTP Adapter response

I was checking out IBM worklight and used HTTP Adapters. In my Rest response I get so many details. I want to filter the records like send the specific nodes to the app as response.
For example
Google distance API URL
It returns so many data which I don't need and I want to send filtered records to app like,
distance: {
"value": 1734542,
"text": "1 735 km"
}
Is it possible anyway in the Worklight HTTP Adapters
sure, you can use JavaScript to filter data and create only response that you need. In case you use XML based web-service you can even use XSLT transformation.
In case your webservice returns JSON like the one you've provided, use something like:
var backendResponse = WL.Server.invokeHttp(....);
var adapterResponse = {
distanceValue : backendResponse.somePropertyDescribingDistanceValue,
distanceText : backendResponse.someOtherPropertyDescribingDistanceText
};
return adapterResponse;
You can use xsl filter in adapter for filtering the contents of the response as well.