Wiremock request not matching even with anyRequestedFor(anyUrl()) - junit

I have a java service and using junit 4.x as test framework. I am using the junit #Rule in test file like this:
#Rule public WireMockRule wireMockRule = new WireMockRule(12345);
This is the test case:
#Test
public void test() throws MessageException {
stubFor(get(urlPathEqualTo("/deal_catalog/v1/lookupId"))
.willReturn(aResponse().withBody(
"\"deal\": {" +
"\"id\": " + dealId.toString() +
"}"
)));
DoSomethingTriggersAHTTPCall();
WireMock.verify(anyRequestedFor(anyUrl()));
I am trying to verify a request with a url path but it kept failing. So I decided to test the loosest condition but it is still failing for me. Really desperate, any suggestion?
Expected at least one request matching: {
"method" : "ANY"
}
Requests received: [ {
"url" : "/deal_catalog/v1/deals/lookupId?clientId=deal_catalog_team&inventoryProductId=3f4f32ff-80f6-40f9-8ae7-8a09ec3dafd2",
"absoluteUrl" : "http://localhost:12345/deal_catalog/v1/deals/lookupId?clientId=deal_catalog_team&inventoryProductId=3f4f32ff-80f6-40f9-8ae7-8a09ec3dafd2",
"method" : "GET",
"clientIp" : "127.0.0.1",
"headers" : {
"Connection" : "keep-alive",
"User-Agent" : "okhttp/3.13.1",
"Host" : "localhost:12345",
"Accept-Encoding" : "gzip"
},
"cookies" : { },
"browserProxyRequest" : false,
"loggedDate" : 1619815885486,
"bodyAsBase64" : "",
"body" : "",
"scheme" : "http",
"host" : "localhost",
"port" : 12345,
"loggedDateString" : "2021-04-30T20:51:25Z",
"queryParams" : {
"clientId" : {
"key" : "clientId",
"values" : [ "deal_catalog_team" ]
},
"inventoryProductId" : {
"key" : "inventoryProductId",
"values" : [ "3f4f32ff-80f6-40f9-8ae7-8a09ec3dafd2" ]
}
}
} ]
==== Update ====
I think I figured this out. I was doing a functional test on the behavior of an async process triggered by a message (pub/sub). The Processor interface is like this:
public interface MessageProcessor<T> {
void process(ReceivedMessage<T> message);
}
The problem is that I didn't call the process method and test the behavior. Instead, I published a message to the in memory message queue and that triggers the void process(ReceivedMessage<T> message); asynchronously. I guess when verify() method is invoked, the outgoing http call in process() has not happened yet. But when wiremock generates the failure report, it already happened so the it is shown in the failure report.
After I switched to call process() directly in test, it passed.

Related

How to retrieve all key-value pairs avoiding key duplication from JSON in Groovy script

I am totally new to groovy script and would like some help to solve this out. I have a JSON response I want to manipulate and get desired parameters back by avoiding duplication. The Json response does not have indexes like 0,1,2.. that I can iterate through.
Here is the response that I want to work with:
{
"AuthenticateV2" : {
"displayName" : "Verification of authentication",
"description" : "notification ",
"smsTemplate" : "authentication.v2.0_sms",
"emailHeaderTemplate" : "v2.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE"
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordRecovery" : {
"displayName" : "Verification of password recovery",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "recovery.v1.0_body_html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordReset" : {
"displayName" : "password reset",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
}
The expected output that I want to have:
{
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL"
}
I need to retrieve all fields under parameters tag and also want to avoid duplication
You should first get familiar with parsing and producing JSON in Groovy.
Then, assuming the provided response is a valid JSON (it's not - there are 2 closing curlies (}) missing at the end) to get all the parameters keys merged into one JSON we have to convert the JSON string into a Map object first using JsonSlurper:
def validJsonResponse = '<your valid JSON string>'
Map parsedResponse = new JsonSlurper().parseText(validJsonResponse) as Map
Now, when we have a parsedResponse map we can iterate over all the root items in the response and transform them into the desired form (which is all the unique parameters keys) using Map::collectEntries method:
Map uniqueParameters = parsedResponse.collectEntries { it.value['parameters'] }
Finally, we can convert the uniqueParameters result back into a pretty printed JSON string using JsonOuput:
println JsonOutput.prettyPrint(JsonOutput.toJson(uniqueParameters))
After applying all the above we'll get the output
{
"displayName": "USER_DISPLAY_NAME",
"actionTokenURL": "VERIFICATION_LINK",
"customToken": "VERIFICATION_CODE",
"adminInitiated": false,
"authnId": "AUTHENTICATION_IDENTIFIER",
"authnType": "EMAIL",
"user": {
"displayName": "USER_DISPLAY_NAME"
}
}
If you want to get rid of user entry from the final output just remove it from the resulting uniqueParameters map (uniqueParameters.remove('user')) before converting it back to JSON string.

Unable to parse expectation on mockserver-netty when adding Content-Type header

I have an integration test where I am using mockserver-netty (v5.3.0) with a springboot 2.0 application..everything is working fine but if I try to add the Content-Type header, I get the following exception:
java.lang.IllegalArgumentException: Exception while parsing [{
"httpRequest" : {
"method" : "POST",
"body" : {
"type" : "XML",
"xml" : "......"
},
"times" : {
"remainingTimes" : 0,
"unlimited" : true
},
"timeToLive" : {
"unlimited" : true
}
}] for Expectation
at org.mockserver.client.AbstractClient.sendRequest(AbstractClient.java:95)
at org.mockserver.client.AbstractClient.sendExpectation(AbstractClient.java:441)
at org.mockserver.client.ForwardChainExpectation.respond(ForwardChainExpectation.java:25)
The expectation is the following:
{
"method" : "POST",
"body" : {
"type" : "XML",
"xml" : "......"
}
},
"httpResponse" : {
"statusCode" : 200,
"headers" : {
"Content-Type" : [ "text/xml" ]
},
"body" : "......."
},
"times" : {
"remainingTimes" : 0,
"unlimited" : true
},
"timeToLive" : {
"unlimited" : true
}
}
I create it with the following code:
private static HttpResponse responseWithBody(String responseBody, int statusCode, String contentType) {
return HttpResponse.response()
.withStatusCode(statusCode)
.withHeader("Content-Type",contentType)
.withBody(responseBody);
}
If I just comment the line with the .withHeader("Content-Type",contentType) statement, everything runs fine. Any clue about that?
Thanks a lot
I got the same problem. Looks like it was caused by a bug in xml parser used underneath, see https://github.com/jamesdbloom/mockserver/issues/451
Upgrade to mockserver 5.4.1 and you'll be fine :)

Spring Data Solr Repository Highlight HATEOAS

I have defined a #Highlight query on my Solr repository class which returns the interesting 'snipplets' info if I call it from another class/controller. However if I access the method through the implicit rest service exposed via #RepositoryRestResource ( e.g. http://localhost:8080/modules/search/findByDescriptionContaining?description=maths ) , it doesn't return any highlighting/snipplet info at all
#RepositoryRestResource
interface ModuleRepository extends SolrCrudRepository<Module, String>{
#Highlight(prefix = "<b>", postfix = "</b>")
HighlightPage<Module> findByDescriptionContaining(#Param(value = "description") String description, Pageable pageable)
}
so to recap, calling the auto exposed method will return this:
{
"_embedded" : {
"modules" : [ {
"name" : "science",
"description" : "a somewhat scientific course with some maths",
"_links" : {
"self" : {
"href" : "http://localhost:8080/modules/102"
},
"module" : {
"href" : "http://localhost:8080/modules/102"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/modules/search/findByDescriptionContaining?description=maths"
}
},
"page" : {
"size" : 20,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
how can I get the highlighting info using the method above ?

Matching data in JsonPath with wiremock

I'm trying to create mocks for my login procedure. I use POST method with a couple of fields and login object (with login, password, etc.)
For that I'm using JsonPath. Code below:
{
"request": {
"method": "POST",
"url": "/login",
"bodyPatterns" : [
{"matchesJsonPath" : "$.method"},
{"matchesJsonPath" : "$.params[?(#.clientVersion == "1")]"},
{"matchesJsonPath" : "$.params.login"},
{"matchesJsonPath" : "$.params.password"}
]
},
"response": {
"status": 200,
"bodyFileName": "login.json"
}
}
I'm checking the clientVersion because it's similar to the examples.
My problem is, that with te given POST JSON:
{
"method": "login",
"params": {
"clientVersion": "1",
"login": "test#test.com",
"password": "681819535da188b6ef2"
}
}
I receive 404.
However, when I change
{"matchesJsonPath" : "$.params[?(#.clientVersion == "1")]"},
to normal
{"matchesJsonPath" : "$.params.clientVersion"},
everything works just fine.
So - how to check inside wiremock, using matchesJsonPath if given field equals some value?
How to apply it to the root field like method in my case?
And while we're at it - I had similar problems with checking if the value is not null. I tried to apply regular expressions and such - no luck.
It's working in my case :
wiremock:
"request": {
"urlPathPattern": "/api/authins-portail-rs/authins/inscription/infosperso",
"bodyPatterns" : [
{"matchesJsonPath" : "$[?(#.nir == '123456789')]"},
{"matchesJsonPath" : "$[?(#.nomPatronyme == 'aubert')]"},
{"matchesJsonPath" : "$[?(#.prenoms == 'christian')]"},
{"matchesJsonPath" : "$[?(#.dateNaissance == '01/09/1952')]"}
],
"method": "POST"
}
Json:
{
"nir": "123456789",
"nomPatronyme": "aubert",
"prenoms": "christian",
"dateNaissance": "01/09/1952"
}
Following worked for me.
"matchesJsonPath" : "$.rootItem.itemA[0].item..[?(#.fieldName=='file')]"
Json :
{
"rootItem" : {
"itemA" : [
{
"item" : {
"fieldName" : "file",
"name" : "test"
}
}
]
}
}
Wiremock
{
"request" : {
"urlPattern" : "/testjsonpath",
"method" : "POST",
"bodyPatterns" : [ {
"matchesJsonPath" : "$.rootItem.itemA[0].item..[?(#.fieldName=='file')]"
} ]
},
"response" : {
"status" : 200,
"body" : "{\"result\": \"success\"}",
"headers" : {
"Content-Type" : "application/json"
}
}
}
Update Wiremock. It should work with newer versions >= 2.0.0-beta. Its JsonPath dependency was very outdated (GitHub #261).
Using the double dots operator is semantically not the same, as the filter will also match for elements with the same name deeper down the tree.
try with double dots operator (recursive)
$..params[?(#.clientVersion == "1")]

How to chain a router after a custom splitter in Camel

I would like to pluck documents from a JSON payload and send them to different processors based on their location.
JSON:
{
"email" : {
"documents" : [{
"name" : "Document 1",
"id" : "1111"
}, {
"name" : "Document 2",
"id" : "222"
}
]
},
"sms" : {
"documents" : [{
"name" : "Document 3",
"id" : "3333"
}, {
"name" : "Document 4",
"id" : "4444"
}
]
}
}
I was thinking to achieve this by doing something like this:
from("servlet:///doc").unmarshal()
.json(JsonLibrary.Jackson, DocumentRequest.class)
.split().method("docSplit", "split")
.choice()
.when().header("mode").isEqualTo("email")
.to("direct:email")
.when().header("mode").isEqualTo("sms")
.to("direct:sms");
My splitter can receive a DocumentRequest and pull out all the docs... but I do not know how to set the "mode" header for future routing.
How can I set the "mode" header?
Is there a better overall approach?
You can always put custom split logic in a custom processor and use ProducerTemplate
For example:
from("servlet:///doc").unmarshal()
.json(JsonLibrary.Jackson, DocumentRequest.class)
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
ProducerTemplate producer=exchange.getContext().createProducerTemplate();
String mode;
for (Document doc: // split and set mode logic goes here ) {
if (mode.compareToIgnoreCase("email") ==0) {
producer.sendBody("direct:email", doc);
} else
if (mode.compareToIgnoreCase("sms") ==0) {
producer.sendBody("direct:sms", doc);
}
...
}
}
});