Repository: authorjapps/zerocode
Pull request #313 (2019-09-18 17:03:38)

ISS-312 - STRICT compare payload


Patch:
diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/Step.java b/core/src/main/java/org/jsmart/zerocode/core/domain/Step.java
index 622510b4..a0456a78 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/domain/Step.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/domain/Step.java
@@ -19,9 +19,10 @@ public class Step {
     private final String method;
     private final String operation;
     private final String url;
-    private JsonNode request;
-    private JsonNode assertions;
-    private JsonNode verify;
+    private final JsonNode request;
+    private final JsonNode assertions;
+    private final String verifyMode;
+    private final JsonNode verify;
     private String id;
     private JsonNode stepFile;
     private List<Object> parameterized;
@@ -63,6 +64,10 @@ public class Step {
         return verify;
     }
 
+    public String getVerifyMode() {
+        return verifyMode;
+    }
+
     public String getId() {
         return id;
     }
@@ -105,10 +110,12 @@ public class Step {
             @JsonProperty("url") String url,
             @JsonProperty("request") JsonNode request,
             @JsonProperty("assertions") JsonNode assertions,
-            @JsonProperty("verify") JsonNode verify) {
+            @JsonProperty("verify") JsonNode verify,
+            @JsonProperty("verifyMode")String verifyMode) {
         this.loop = loop;
         this.retry = retry;
         this.name = name;
+        this.verifyMode = verifyMode;
         this.operation = operation != null? operation : method;
         this.method = method != null? method : operation;
         this.request = request;
@@ -128,6 +135,7 @@ public class Step {
                 ", url='" + url + '\'' +
                 ", request=" + request +
                 ", assertions=" + assertions +
+                ", verifyMode=" + verifyMode +
                 ", verify=" + verify +
                 ", id='" + id + '\'' +
                 ", stepFile=" + stepFile +
diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java
index 9055f2b6..b10ca720 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java
@@ -1,13 +1,20 @@
 package org.jsmart.zerocode.core.runner;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.PathNotFoundException;
 import com.univocity.parsers.csv.CsvParser;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
 import org.jsmart.zerocode.core.domain.ScenarioSpec;
 import org.jsmart.zerocode.core.domain.Step;
 import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecReportBuilder;
@@ -26,14 +33,20 @@ import org.junit.runner.Description;
 import org.junit.runner.notification.RunNotifier;
 import org.slf4j.Logger;
 
+import static java.util.Optional.ofNullable;
 import static org.jsmart.zerocode.core.constants.ZerocodeConstants.KAFKA_TOPIC;
 import static org.jsmart.zerocode.core.domain.builders.ZeroCodeExecReportBuilder.newInstance;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aMatchingMessage;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aNotMatchingMessage;
 import static org.jsmart.zerocode.core.engine.mocker.RestEndPointMocker.wireMockServer;
 import static org.jsmart.zerocode.core.kafka.helper.KafkaCommonUtils.printBrokerProperties;
+import static org.jsmart.zerocode.core.utils.HelperJsonUtils.strictComparePayload;
 import static org.jsmart.zerocode.core.utils.RunnerUtils.getFullyQualifiedUrl;
 import static org.jsmart.zerocode.core.utils.RunnerUtils.getParameterSize;
 import static org.jsmart.zerocode.core.utils.ApiTypeUtils.apiType;
 import static org.jsmart.zerocode.core.utils.SmartUtils.prettyPrintJson;
+import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
+import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT;
 import static org.slf4j.LoggerFactory.getLogger;
 
 @Singleton
@@ -226,8 +239,7 @@ public class ZeroCodeMultiStepsScenarioRunnerImpl implements ZeroCodeMultiStepsS
                 // -----------------
                 // logging assertion
                 // -----------------
-                List<JsonAsserter> asserters = zeroCodeAssertionsProcessor.createJsonAsserters(resolvedAssertionJson);
-                List<FieldAssertionMatcher> failureResults = zeroCodeAssertionsProcessor.assertAllAndReturnFailed(asserters, executionResult);
+                List<FieldAssertionMatcher> failureResults = compareStepResults(thisStep, executionResult, resolvedAssertionJson);
 
                 if (!failureResults.isEmpty()) {
                     StringBuilder builder = new StringBuilder();
@@ -481,4 +493,16 @@ public class ZeroCodeMultiStepsScenarioRunnerImpl implements ZeroCodeMultiStepsS
         scenarioLoopTimes = parameterSize != 0 ? parameterSize : scenarioLoopTimes;
         return scenarioLoopTimes;
     }
+
+    private List<FieldAssertionMatcher> compareStepResults(Step thisStep, String actualResult, String expectedResult) {
+        List<FieldAssertionMatcher> failureResults = new ArrayList<>();
+        if (ofNullable(thisStep.getVerifyMode()).orElse("LENIENT").equals("STRICT")) {
+            failureResults = strictComparePayload(expectedResult, actualResult);
+        } else {
+            List<JsonAsserter> asserters = zeroCodeAssertionsProcessor.createJsonAsserters(expectedResult);
+            failureResults = zeroCodeAssertionsProcessor.assertAllAndReturnFailed(asserters, actualResult);
+        }
+        return failureResults;
+    }
+
 }
diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/HelperJsonUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/HelperJsonUtils.java
index 2c23b556..6a91663b 100755
--- a/core/src/main/java/org/jsmart/zerocode/core/utils/HelperJsonUtils.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/utils/HelperJsonUtils.java
@@ -1,16 +1,29 @@
 package org.jsmart.zerocode.core.utils;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.PathNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.commons.lang.StringUtils;
 import org.jboss.resteasy.client.ClientRequest;
 import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider;
+import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aMatchingMessage;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aNotMatchingMessage;
+import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
+import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT;
+
 // TODO: Move this to Smartutils class
 public class HelperJsonUtils {
     private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(HelperJsonUtils.class);
@@ -97,4 +110,62 @@ public class HelperJsonUtils {
             throw new RuntimeException("Exception while converting IPT Java Object to JsonString" + e);
         }
     }
+
+
+    public static List<FieldAssertionMatcher> strictComparePayload(String expectedResult, String actualResult) {
+        List<FieldAssertionMatcher> matchers = new ArrayList<>();
+
+        String actualResultJson = readPayload(actualResult);
+        String expectedResultJson = readPayload(expectedResult);
+        try {
+            assertEquals(expectedResultJson, actualResultJson, STRICT);
+        } catch (AssertionError scream) {
+            String rawMsg = scream.getMessage();
+            List<String> messageList = Arrays.asList(rawMsg.split(";"));
+            matchers = messageList.stream()
+                    .map(msg -> {
+                        List<String> strings = Arrays.asList(msg.trim().split("\n"));
+                        String fieldJsonPath = "";
+                        if(strings != null && strings.size() > 0){
+                            fieldJsonPath = strings.get(0).substring(strings.get(0).indexOf(": ") + 1).trim();
+                        }
+                        if (strings.size() == 1) {
+                            return aNotMatchingMessage(fieldJsonPath, "", strings.get(0).trim());
+                        } else if (strings.size() == 2) {
+                            return aNotMatchingMessage(fieldJsonPath, "", strings.get(1).trim());
+                        } else if (strings.size() > 2) {
+                            return aNotMatchingMessage(fieldJsonPath, strings.get(1).trim(), strings.get(2).trim());
+                        } else {
+                            return aMatchingMessage();
+                        }
+                    })
+                    .collect(Collectors.toList());
+        }
+
+        return matchers;
+    }
+
+    private static String readPayload(String json) {
+        String bodyPath = "$.body";
+        String rawBodyPath = "$.rawBody";
+
+        Map payload = (Map) readJsonPathOrElseNull(json, bodyPath);
+        payload = payload == null ? (Map) readJsonPathOrElseNull(json, rawBodyPath) : payload;
+
+        try {
+            return mapper.writeValueAsString(payload);
+        } catch (JsonProcessingException ex) {
+            LOGGER.debug("Exception while reading payload - " + ex);
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public static Object readJsonPathOrElseNull(String requestJson, String jsonPath) {
+        try {
+            return JsonPath.read(requestJson, jsonPath);
+        } catch (PathNotFoundException pEx) {
+            LOGGER.debug("No " + jsonPath + " was present in the request. returned null.");
+            return null;
+        }
+    }
 }
diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java
index 5b06fcd1..b9a941ef 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java
@@ -1,5 +1,6 @@
 package org.jsmart.zerocode.core.utils;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -12,6 +13,7 @@ import com.google.inject.Singleton;
 import com.google.inject.name.Named;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -22,15 +24,20 @@ import java.util.stream.Collectors;
 import org.apache.commons.lang.text.StrSubstitutor;
 import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider;
 import org.jsmart.zerocode.core.domain.ScenarioSpec;
+import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static java.nio.charset.Charset.defaultCharset;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aMatchingMessage;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aNotMatchingMessage;
+import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
+import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT;
 
 @Singleton
 public class SmartUtils {
     private static final Logger LOGGER = LoggerFactory.getLogger(SmartUtils.class);
-    
+
     @Inject
     private ObjectMapper mapper; //<--- remember the static methods can not use this objectMapper. So make the methods non-static if you want to use this objectMapper.
 
diff --git a/pom.xml b/pom.xml
index a7794aaf..cafcdb17 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,7 +65,7 @@
         <junit.version>4.12</junit.version>
         <jackson-databind.version>2.9.8</jackson-databind.version>
         <guava.version>23.0</guava.version>
-        <jsonassert.version>1.2.3</jsonassert.version>
+        <jsonassert.version>1.5.0</jsonassert.version>
         <classpath-explorer.version>1.0</classpath-explorer.version>
         <jukito.version>1.4.1</jukito.version>
         <guice.version>4.0</guice.version>


Test patch:
diff --git a/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java b/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java
index f9132ee9..ff63bf54 100644
--- a/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java
+++ b/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java
@@ -5,23 +5,29 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Inject;
 import com.jayway.jsonpath.JsonPath;
 import com.univocity.parsers.csv.CsvParser;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
+import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
 import org.jsmart.zerocode.core.utils.SmartUtils;
 import org.jukito.JukitoRunner;
 import org.jukito.TestModule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.skyscreamer.jsonassert.JSONAssert;
-
-import java.util.HashMap;
-import java.util.Map;
+import org.skyscreamer.jsonassert.JSONCompareMode;
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.jsmart.zerocode.core.di.provider.CsvParserProvider.LINE_SEPARATOR;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aMatchingMessage;
+import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aNotMatchingMessage;
 
 @RunWith(JukitoRunner.class)
 // Or use - @UseModules(ApplicationMainModule.class)
@@ -60,11 +66,8 @@ public class StepTest {
         assertThat(queryParams.toString(), is("{param1=value1, invId=10101}"));
         assertThat(requestHeaders.toString(), is("{Content-Type=application/json;charset=UTF-8, Cookie=cookie_123}"));
 
-        //Map<String, Object> headerMap = smartUtils.readJsonStringAsMap(requestHeaders.toString());
-        //Map<String, Object> queryParamsMap = smartUtils.readJsonStringAsMap(queryParams.toString());
-
-        Map<String, Object> headerMap = (HashMap)requestHeaders;
-        Map<String, Object> queryParamsMap = (HashMap)queryParams;
+        Map<String, Object> headerMap = (HashMap) requestHeaders;
+        Map<String, Object> queryParamsMap = (HashMap) queryParams;
 
         assertThat(headerMap.get("Cookie"), is("cookie_123"));
         assertThat(queryParamsMap.get("invId"), is(10101));
@@ -81,6 +84,7 @@ public class StepTest {
 
         assertThat(stepDeserialized.getVerify().get("status").asText(), is("201"));
         assertThat(stepDeserialized.getAssertions().get("status").asText(), is("201"));
+        assertThat(stepDeserialized.getVerifyMode(), is("STRICT"));
     }
 
     @Test
@@ -131,7 +135,7 @@ public class StepTest {
         JsonNode singleStepNode = mapper.valueToTree(stepJava);
         String singleStepNodeString = mapper.writeValueAsString(singleStepNode);
 
-        JSONAssert.assertEquals(jsonDocumentAsString,singleStepNodeString, false);
+        JSONAssert.assertEquals(jsonDocumentAsString, singleStepNodeString, false);
 
         assertThat(singleStepNode.get("name").asText(), is("StepNameWithoutSpaceEgCREATE"));
         assertThat(singleStepNode.get("loop").asInt(), is(3));
@@ -161,7 +165,134 @@ public class StepTest {
         JsonNode singleStepNode = mapper.valueToTree(stepJava);
         String singleStepNodeString = mapper.writeValueAsString(singleStepNode);
 
-        JSONAssert.assertEquals(jsonDocumentAsString,singleStepNodeString, false);
+        JSONAssert.assertEquals(jsonDocumentAsString, singleStepNodeString, false);
         assertThat(singleStepNode.get("method").asText(), is("POST"));
     }
+
+    @Test
+    public void testPayLoad_strictPass() {
+        String actual = "{\n" +
+                "    \"id\": 123,\n" +
+                "    \"type\": \"Premium High Value\",\n" +
+                "    \"office\":{\n" +
+                "        \"type\": \"branches\",\n" +
+                "        \"locations\":[\n" +
+                "            {\n" +
+                "                \"country\": \"UK\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    },\n" +
+                "    \"addresses\": [\n" +
+                "        {\n" +
+                "            \"type\": \"home\",\n" +
+                "            \"line1\": \"10 Random St\"\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        String expected = "{\n" +
+                //"    \"id\": 123,\n" +
+                "    \"type\": \"Premium High Value\",\n" +
+                "    \"office\":{\n" +
+                "        \"type\": \"branches\",\n" +
+                "        \"locations\":[\n" +
+                "            {\n" +
+                "                \"country\": \"UK\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    },\n" +
+                "    \"addresses\": [\n" +
+                "        {\n" +
+                "            \"type\": \"home\",\n" +
+                "            \"line1\": \"10 Random St\"\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        try {
+            JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT);
+
+        } catch (Throwable ex) {
+            assertThat(ex.getMessage(), containsString("Unexpected: id"));
+        }
+    }
+
+    @Test
+    public void testPayLoad_strictFail_FieldAssertion() {
+        List<FieldAssertionMatcher> matchers = new ArrayList<>();
+
+        String actual = "{\n" +
+                "    \"office\":{\n" +
+                "        \"type\": \"branches\",\n" +
+                "        \"locations\":[\n" +
+                "            {\n" +
+                "                \"country\": \"UK\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    },\n" +
+                "    \"exactMatches\": true,\n" +
+                "    \"foo\": \"Mr FooX\",\n" +
+                "    \"name\": \"Mr Bean\",\n" +
+                "    \"city\": \"Lon\",\n" +
+                "    \"listings\":[\n" +
+                "        {\n" +
+                "            \"exchange\": \"NYX\"\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        String expected = "{\n" +
+                "    \"office\":{\n" +
+                "        \"type\": \"branches\",\n" +
+                "        \"locations\":[\n" +
+                "            {\n" +
+                "                \"country\": \"FRANCE\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    },\n" +
+                //"    \"exactMatches\": true,\n" +
+                "    \"foo\": \"Mr FooX\",\n" +
+                "    \"city\": \"Lon\",\n" +
+                "    \"listings\":[\n" +
+                "        {\n" +
+                "            \"exchange\": \"NYX\"\n" +
+                "        }\n" +
+                "    ],\n" +
+                "    \"addresses\":[\n" +
+                "        {\n" +
+                "            \"type\": \"office\"\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        try {
+
+            JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT);
+
+        } catch (AssertionError ex) {
+            String message = ex.getMessage();
+            List<String> errorMsgs = Arrays.asList(message.split(";"));
+            matchers = errorMsgs.stream()
+                    .map(msg -> {
+                        List<String> strings = Arrays.asList(msg.trim().split("\n"));
+                        String fieldJsonPath = "";
+                        if(strings != null && strings.size() > 0){
+                            fieldJsonPath = strings.get(0).substring(strings.get(0).indexOf(": ") + 1).trim();
+                        }
+                        if (strings.size() == 1) {
+                            return aNotMatchingMessage(fieldJsonPath, "", strings.get(0).trim());
+                        } else if (strings.size() == 2) {
+                            return aNotMatchingMessage(fieldJsonPath, "", strings.get(1).trim());
+                        } else if (strings.size() > 2) {
+                            return aNotMatchingMessage(fieldJsonPath, strings.get(1).trim(), strings.get(2).trim());
+                        } else {
+                            return aMatchingMessage();
+                        }
+                    })
+                    .collect(Collectors.toList());
+        }
+
+        assertThat(matchers.size(), is(4));
+        assertThat(matchers.get(0).toString(), is("Assertion jsonPath 'addresses' with actual value 'but none found' did not match the expected value ''"));
+        assertThat(matchers.get(1).toString(), is("Assertion jsonPath 'office.locations[0].country' with actual value 'got: UK' did not match the expected value 'Expected: FRANCE'"));
+        assertThat(matchers.get(2).toString(), is("Assertion jsonPath 'exactMatches' with actual value 'Unexpected: exactMatches' did not match the expected value ''"));
+        assertThat(matchers.get(3).toString(), is("Assertion jsonPath 'name' with actual value 'Unexpected: name' did not match the expected value ''"));
+    }
+
 }
\ No newline at end of file
diff --git a/core/src/test/java/org/jsmart/zerocode/integrationtests/HelloWorldInMemoryTest.java b/core/src/test/java/org/jsmart/zerocode/integrationtests/HelloWorldInMemoryTest.java
new file mode 100644
index 00000000..0c765bbb
--- /dev/null
+++ b/core/src/test/java/org/jsmart/zerocode/integrationtests/HelloWorldInMemoryTest.java
@@ -0,0 +1,28 @@
+package org.jsmart.zerocode.integrationtests;
+
+import org.jsmart.zerocode.core.domain.HostProperties;
+import org.jsmart.zerocode.core.domain.JsonTestCase;
+import org.jsmart.zerocode.core.domain.Scenario;
+import org.jsmart.zerocode.core.tests.customrunner.TestOnlyZeroCodeUnitRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@HostProperties(host="http://localhost", port=9998, context = "")
+@RunWith(TestOnlyZeroCodeUnitRunner.class)
+public class HelloWorldInMemoryTest {
+
+    /**
+     * Mock end points are in test/resources: simulators/test_purpose_end_points.json.
+     * @RunWith(TestOnlyZeroCodeUnitRunner.class) : starts these mocks first before running the tests
+     */
+
+    @Test
+    @JsonTestCase("integration_test_files/helloworld/get_api_integration_test.json")
+    public void testStrict_compare() throws Exception {
+    
+    }
+
+}
+
+
+
diff --git a/core/src/test/java/org/jsmart/zerocode/integrationtests/HelloWorldStrictModeTest.java b/core/src/test/java/org/jsmart/zerocode/integrationtests/HelloWorldStrictModeTest.java
new file mode 100644
index 00000000..4f411f32
--- /dev/null
+++ b/core/src/test/java/org/jsmart/zerocode/integrationtests/HelloWorldStrictModeTest.java
@@ -0,0 +1,30 @@
+package org.jsmart.zerocode.integrationtests;
+
+import org.jsmart.zerocode.core.domain.HostProperties;
+import org.jsmart.zerocode.core.domain.JsonTestCase;
+import org.jsmart.zerocode.core.tests.customrunner.TestOnlyZeroCodeUnitRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@HostProperties(host="http://localhost", port=9998, context = "")
+@RunWith(TestOnlyZeroCodeUnitRunner.class)
+public class HelloWorldStrictModeTest {
+
+    /**
+     * Mock end points are in test/resources: simulators/test_purpose_end_points.json.
+     * @RunWith(TestOnlyZeroCodeUnitRunner.class) : starts these mocks first before running the tests
+     *
+     * Path:
+     * src/test/resources/simulators/test_purpose_end_points.json
+     */
+
+    @Test
+    @JsonTestCase("integration_test_files/helloworld/get_api_integration_STRICT_test.json")
+    public void testStrict_compareStrict() throws Exception {
+    
+    }
+
+}
+
+
+
diff --git a/core/src/test/resources/integration_test_files/helloworld/get_api_integration_STRICT_test.json b/core/src/test/resources/integration_test_files/helloworld/get_api_integration_STRICT_test.json
new file mode 100644
index 00000000..5323af31
--- /dev/null
+++ b/core/src/test/resources/integration_test_files/helloworld/get_api_integration_STRICT_test.json
@@ -0,0 +1,34 @@
+{
+    "scenarioName": "As simple GET API - Strict validation",
+    "steps": [
+        {
+            "name": "find_match",
+            "url": "/api/v1/search/people",
+            "method": "GET",
+            "request": {
+                "queryParams": {
+                    "city": "Lon"
+                }
+            },
+            "verifyMode":"STRICT",
+            "verify": {
+                "status": 200,
+                "body": {
+                    "exactMatches": false,
+                    "bio": "name-only",
+                    "searchMatches":[
+                        {
+                            "name": "Mr Bean",
+                            "char": "Kids"
+                        },
+                        {
+                            "name": "Mr Bean",
+                            "char": "Adults"
+                        }
+                    ]
+                }
+            }
+        }
+    ]
+}
+
diff --git a/core/src/test/resources/integration_test_files/helloworld/get_api_integration_test.json b/core/src/test/resources/integration_test_files/helloworld/get_api_integration_test.json
new file mode 100644
index 00000000..bc8c35ac
--- /dev/null
+++ b/core/src/test/resources/integration_test_files/helloworld/get_api_integration_test.json
@@ -0,0 +1,26 @@
+{
+    "scenarioName": "As simple GET API - Inetgration Test - Local Server",
+    "steps": [
+        {
+            "name": "find_match",
+            "url": "/api/v1/search/persons",
+            "method": "GET",
+            "request": {
+                "queryParams": {
+                    "lang": "Amazing",
+                    "city": "Lon"
+                }
+            },
+            "verify": {
+                "status": 200,
+                "body": {
+                    "exactMatches": true,
+                    "name": "Mr Bean",
+                    "lang": "Amazing",
+                    "city": "Lon"
+                }
+            }
+        }
+    ]
+}
+
diff --git a/core/src/test/resources/simulators/test_purpose_end_points.json b/core/src/test/resources/simulators/test_purpose_end_points.json
index ea2cba5e..5ce0ae97 100644
--- a/core/src/test/resources/simulators/test_purpose_end_points.json
+++ b/core/src/test/resources/simulators/test_purpose_end_points.json
@@ -100,7 +100,29 @@
                     "city": "Lon"
                 }
             }
+        },
+        {
+            "name": "request with query params",
+            "operation": "GET",
+            "url": "/api/v1/search/people?city=Lon",
+            "response": {
+                "status": 200,
+                "body": {
+                    "exactMatches": false,
+                    "bio": "name-only",
+                    "searchMatches":[
+                        {
+                            "name": "Mr Bean",
+                            "char": "Kids"
+                        },
+                        {
+                            "name": "Mr Bean",
+                            "char": "Adults"
+                        }
+                    ]
+                }
+            }
         }
-
     ]
-}
\ No newline at end of file
+}
+
diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json
index a3a02be0..800313f0 100755
--- a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json
+++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json
@@ -23,5 +23,6 @@
     "body": {
       "id" : 1001
     }
-  }
+  },
+  "verifyMode":"STRICT"
 }