Repository: authorjapps/zerocode
Pull request #266 (2019-06-29 14:36:12)

ISS-67 # Add '$ONE.OF:' functionality 
Added $ONE.OF vanilla case functionality for issue #67 with tests. Empty string values and whitespace values are also supported (for example if actual result is a single whitespace and one of the expected values is a whitespace, the test will pass).

Second PR to fix issue caused by a reference to a Java 11 method in FieldIsOneOfValueAsserter.java (String.isBlank()) in previous PR


Patch:
diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/FieldIsOneOfValueAsserter.java b/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/FieldIsOneOfValueAsserter.java
new file mode 100644
index 00000000..5b33edeb
--- /dev/null
+++ b/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/FieldIsOneOfValueAsserter.java
@@ -0,0 +1,71 @@
+package org.jsmart.zerocode.core.engine.assertion;
+
+import java.util.Arrays;
+
+public class FieldIsOneOfValueAsserter implements JsonAsserter {
+	private final String path;
+	final Object expected;
+
+	@Override
+	public String getPath() {
+		return path;
+	}
+
+	@Override
+	public AssertionReport actualEqualsToExpected(Object actualResult) {
+		boolean areEqual;
+
+		if (expected != null) {
+			String expectedString = (String) expected;
+
+			// Remove json string array brackets
+			if (expectedString.startsWith("["))
+				expectedString = expectedString.substring(1);
+
+			if (expectedString.endsWith("]"))
+				expectedString = expectedString.substring(0, expectedString.length() - 1);
+
+			// Store collection as a java array
+			String[] expectedArray = null;
+			
+			// Check if it's an empty json array
+			if (!expectedString.isEmpty()) {
+				// Split into an array
+				expectedArray = expectedString.split(",");
+			} else {
+				expectedArray = new String[] {};
+			}
+				
+			// Remove leading and trailing spaces
+			for (int i = 0; i < expectedArray.length; i++) {
+				// Checking that this is not a whitespace string (cannot use .isBlank() as we're
+				// targeting java 1.8)
+				if (!expectedArray[i].trim().isEmpty())
+					expectedArray[i] = expectedArray[i].trim();
+			}
+
+			if (actualResult != null) {
+				// Search list for value
+				areEqual = Arrays.asList(expectedArray).contains(actualResult);
+			} else {
+				areEqual = false;
+			}
+		} else {
+			// Both null
+			if (actualResult == null) {
+				areEqual = true;
+			} else {
+				areEqual = false;
+			}
+		}
+
+		return areEqual ? AssertionReport.createFieldMatchesReport()
+				: AssertionReport.createFieldDoesNotMatchReport(path, "One Of:" + expected, actualResult);
+	}
+
+	public FieldIsOneOfValueAsserter(String path, Object expected) {
+		this.path = path;
+		this.expected = expected;
+	}
+
+}
\ No newline at end of file


Test patch:
diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java
index e1e1ced5..4fa2f501 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java
@@ -1,352 +1,356 @@
-/*
- * Copyright (C) 2014 jApps Ltd and
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jsmart.zerocode.core.engine.preprocessor;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.JsonNodeType;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-import com.jayway.jsonpath.JsonPath;
-
-import org.apache.commons.lang.text.StrSubstitutor;
-import org.jsmart.zerocode.core.domain.reports.LocalDateTimeDeserializer;
-import org.jsmart.zerocode.core.engine.assertion.*;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
-
-import static java.lang.String.format;
-import static org.apache.commons.lang.StringEscapeUtils.escapeJava;
-import static org.jsmart.zerocode.core.utils.TokenUtils.*;
-import static org.slf4j.LoggerFactory.getLogger;
-
-public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
-
-    private static final org.slf4j.Logger LOGGER = getLogger(ZeroCodeJsonTestProcesorImpl.class);
-
-    final List<String> propertyKeys = new ArrayList<>();
-    final Properties properties = new Properties();
-
-    // -----------------------
-    // Assertion place holders
-    // -----------------------
-    public static final String ASSERT_VALUE_NOT_NULL = "$NOT.NULL";
-    public static final String ASSERT_VALUE_NULL = "$NULL";
-    public static final String ASSERT_VALUE_EMPTY_ARRAY = "$[]";
-    public static final String ASSERT_PATH_SIZE = ".SIZE";
-    public static final String ASSERT_VALUE_CONTAINS_STRING = "$CONTAINS.STRING:";
-    public static final String ASSERT_VALUE_MATCHES_STRING = "$MATCHES.STRING:";
-    public static final String ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE = "$CONTAINS.STRING.IGNORECASE:";
-    public static final String ASSERT_VALUE_EQUAL_TO_NUMBER = "$EQ.";
-    public static final String ASSERT_VALUE_NOT_EQUAL_TO_NUMBER = "$NOT.EQ.";
-    public static final String ASSERT_VALUE_GREATER_THAN = "$GT.";
-    public static final String ASSERT_VALUE_LESSER_THAN = "$LT.";
-    public static final String ASSERT_LOCAL_DATETIME_AFTER = "$LOCAL.DATETIME.AFTER:";
-    public static final String ASSERT_LOCAL_DATETIME_BEFORE = "$LOCAL.DATETIME.BEFORE:";
-    public static final String ASSERT_PATH_VALUE_NODE = "$";
-    public static final String RAW_BODY = ".rawBody";
-
-    private final ObjectMapper mapper;
-    private final String hostFileName;
-
-    @Inject
-    public ZeroCodeJsonTestProcesorImpl(ObjectMapper mapper, @Named("HostFileName") String hostFileName) {
-        this.mapper = mapper;
-        this.hostFileName = hostFileName;
-        loadAnnotatedHostProperties();
-    }
-
-    @Override
-    public String resolveStringJson(String requestJsonOrAnyString, String scenarioStateJson) {
-        String resolvedFromTemplate = resolveKnownTokensAndProperties(requestJsonOrAnyString);
-        return resolveJsonPaths(resolvedFromTemplate, scenarioStateJson);
-    }
-
-    @Override
-    public String resolveKnownTokensAndProperties(String requestJsonOrAnyString) {
-        Map<String, Object> paramMap = new HashMap<>();
-
-        final List<String> testCaseTokens = getTestCaseTokens(requestJsonOrAnyString);
-
-        testCaseTokens.forEach(runTimeToken -> {
-            populateParamMap(paramMap, runTimeToken);
-
-            if (isPropertyKey(runTimeToken)) {
-                paramMap.put(runTimeToken, properties.get(runTimeToken));
-            }
-
-        });
-
-        StrSubstitutor sub = new StrSubstitutor(paramMap);
-
-        return sub.replace(requestJsonOrAnyString);
-    }
-
-    @Override
-    public String resolveJsonPaths(String jsonString, String scenarioState) {
-        List<String> jsonPaths = getAllJsonPathTokens(jsonString);
-        Map<String, String> paramMap = new HashMap<>();
-
-        jsonPaths.forEach(thisPath -> {
-            try {
-
-                if (thisPath.endsWith(RAW_BODY)) {
-                    /**
-                     * In case the rawBody is used anywhere in the steps as $.step_name.response.rawBody,
-                     * then it must be escaped as the content was not a simple JSON string to be able
-                     * to convert to json. Hence without throwing exception, treat as string content.
-                     *
-                     * Use escapeJava, do not use escapeJavaScript, as escapeJavaScript also escapes single quotes
-                     * which in turn throws Jackson Exception
-                     */
-                    String escapedString = escapeJava(JsonPath.read(scenarioState, thisPath));
-                    paramMap.put(thisPath, escapedString);
-
-                } else {
-                    // if it is a json block/node or array, this return value is LinkedHashMap.
-                    if (JsonPath.read(scenarioState, thisPath) instanceof LinkedHashMap) {
-                        final String pathValue = mapper.writeValueAsString(JsonPath.read(scenarioState, thisPath));
-                        String escapedPathValue = escapeJava(pathValue);
-                        paramMap.put(thisPath, escapedPathValue);
-
-                    } else {
-                        // Usual flow
-                        paramMap.put(thisPath, JsonPath.read(scenarioState, thisPath));
-
-                    }
-
-                }
-
-            } catch (Exception e) {
-                throw new RuntimeException("\nJSON:" + jsonString + "\nPossibly comments in the JSON found or bad JSON path found: " + thisPath + ", Details: " + e);
-            }
-        });
-
-        StrSubstitutor sub = new StrSubstitutor(paramMap);
-
-        return sub.replace(jsonString);
-    }
-
-    @Override
-    public List<String> getAllJsonPathTokens(String requestJsonAsString) {
-        List<String> jsonPaths = new ArrayList<>();
-
-        final List<String> allTokens = getTestCaseTokens(requestJsonAsString);
-        allTokens.forEach(thisToken -> {
-            if (thisToken.startsWith("$.")) {
-                jsonPaths.add(thisToken);
-            }
-        });
-
-        return jsonPaths;
-    }
-
-    @Override
-    public List<JsonAsserter> createAssertersFrom(String resolvedAssertionJson) {
-        List<JsonAsserter> asserters = new ArrayList<>();
-        try {
-            JsonNode jsonNode = mapper.readTree(resolvedAssertionJson);
-
-            Map<String, Object> createFieldsKeyValuesMap = createAssertionKV(jsonNode, "$.");
-
-            int i = 1;
-            for (Map.Entry<String, Object> entry : createFieldsKeyValuesMap.entrySet()) {
-                String path = entry.getKey();
-                Object value = entry.getValue();
-
-                JsonAsserter asserter;
-                if (ASSERT_VALUE_NOT_NULL.equals(value)) {
-                    asserter = new FieldIsNotNullAsserter(path);
-                } else if (ASSERT_VALUE_NULL.equals(value)) {
-                    asserter = new FieldIsNullAsserter(path);
-                } else if (ASSERT_VALUE_EMPTY_ARRAY.equals(value)) {
-                    asserter = new ArrayIsEmptyAsserter(path);
-                } else if (path.endsWith(ASSERT_PATH_SIZE)) {
-                    path = path.substring(0, path.length() - ASSERT_PATH_SIZE.length());
-                    if (value instanceof Number) {
-                        asserter = new ArraySizeAsserter(path, ((Integer) value).intValue());
-                    } else if (value instanceof String) {
-                        asserter = new ArraySizeAsserter(path, (String) value);
-                    } else {
-                        throw new RuntimeException(format("Oops! Unsupported value for .SIZE: %s", value));
-                    }
-                } else if (value instanceof String && ((String) value).startsWith(ASSERT_VALUE_CONTAINS_STRING)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_CONTAINS_STRING.length());
-                    asserter = new FieldHasSubStringValueAsserter(path, expected);
-                } else if (value instanceof String && ((String) value).startsWith(ASSERT_VALUE_MATCHES_STRING)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_MATCHES_STRING.length());
-                    asserter = new FieldMatchesRegexPatternAsserter(path, expected);
-                } else if (value instanceof String && ((String) value).startsWith(ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE.length());
-                    asserter = new FieldHasSubStringIgnoreCaseValueAsserter(path, expected);
-                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_EQUAL_TO_NUMBER)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_EQUAL_TO_NUMBER.length());
-                    asserter = new FieldHasEqualNumberValueAsserter(path, new BigDecimal(expected));
-                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_NOT_EQUAL_TO_NUMBER)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_NOT_EQUAL_TO_NUMBER.length());
-                    asserter = new FieldHasInEqualNumberValueAsserter(path, new BigDecimal(expected));
-                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_GREATER_THAN)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_GREATER_THAN.length());
-                    asserter = new FieldHasGreaterThanValueAsserter(path, new BigDecimal(expected));
-                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_LESSER_THAN)) {
-                    String expected = ((String) value).substring(ASSERT_VALUE_LESSER_THAN.length());
-                    asserter = new FieldHasLesserThanValueAsserter(path, new BigDecimal(expected));
-                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_LOCAL_DATETIME_AFTER)) {
-                    String expected = ((String) value).substring(ASSERT_LOCAL_DATETIME_AFTER.length());
-                    asserter = new FieldHasDateAfterValueAsserter(path, parseLocalDateTime(expected));
-                }else if (value instanceof String && (value.toString()).startsWith(ASSERT_LOCAL_DATETIME_BEFORE)) {
-                    String expected = ((String) value).substring(ASSERT_LOCAL_DATETIME_BEFORE.length());
-                    asserter = new FieldHasDateBeforeValueAsserter(path, parseLocalDateTime(expected));
-                }
-                else {
-                    asserter = new FieldHasExactValueAsserter(path, value);
-                }
-
-                asserters.add(asserter);
-            }
-        } catch (IOException parEx) {
-            throw new RuntimeException(parEx);
-        }
-
-        return asserters;
-    }
-
-    private Map<String, Object> createAssertionKV(JsonNode jsonNode, String pathDslPrefix) {
-        HashMap<String, Object> resultMap = new HashMap<String, Object>();
-
-        if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) {
-            jsonNode.fieldNames().forEachRemaining(fieldName -> {
-                String qualifiedName = pathDslPrefix + fieldName;
-                JsonNode thisNode = jsonNode.get(fieldName);
-
-                if (thisNode.isValueNode()) {
-                    Object value = convertJsonTypeToJavaType(jsonNode.get(fieldName));
-                    resultMap.put(qualifiedName, value);
-
-                } else {
-                    String newPrefix = qualifiedName + ".";
-                    resultMap.putAll(createAssertionKV(thisNode, newPrefix));
-
-                }
-            });
-
-        } else if (jsonNode.getNodeType().equals(JsonNodeType.ARRAY)) {
-            int i = 0;
-            final Iterator<JsonNode> arrayIterator = jsonNode.elements();
-            while (arrayIterator.hasNext()) {
-                final JsonNode thisElementValue = arrayIterator.next();
-                String elementName = String.format("%s[%d]", pathDslPrefix.substring(0, pathDslPrefix.lastIndexOf('.')), i++);
-
-                if (thisElementValue.isValueNode()) {
-                    Object value = convertJsonTypeToJavaType(thisElementValue);
-                    resultMap.put(elementName, value);
-
-                } else {
-                    String newPrefix = elementName + ".";
-                    resultMap.putAll(createAssertionKV(thisElementValue, newPrefix));
-
-                }
-            }
-        }
-        /*
-         * This is useful when only value is present without a key
-         * i.e. still a valid JSON even if it doesnt start-end with a '{'
-         */
-        else if (jsonNode.isValueNode()) {
-            Object value = convertJsonTypeToJavaType(jsonNode);
-            resultMap.put("$", value);
-
-        } else {
-            throw new RuntimeException(format("Oops! Unsupported JSON Type: %s", jsonNode.getClass().getName()));
-
-        }
-
-        return resultMap;
-    }
-
-    private Object convertJsonTypeToJavaType(JsonNode jsonNode) {
-        if (jsonNode.isValueNode()) {
-            if (jsonNode.isInt()) {
-                return jsonNode.asInt();
-
-            } else if (jsonNode.isTextual()) {
-                return jsonNode.asText();
-
-            } else if (jsonNode.isBoolean()) {
-                return jsonNode.asBoolean();
-
-            } else if (jsonNode.isLong()) {
-                return jsonNode.asLong();
-
-            } else if (jsonNode.isDouble()) {
-                return jsonNode.asDouble();
-
-            } else if (jsonNode.isNull()) {
-                return null;
-
-            } else {
-                throw new RuntimeException(format("Oops! Unsupported JSON primitive to Java : %s by the framework", jsonNode.getClass().getName()));
-            }
-        } else {
-            throw new RuntimeException(format("Unsupported JSON Type: %s", jsonNode.getClass().getName()));
-        }
-    }
-
-    @Override
-    public List<AssertionReport> assertAllAndReturnFailed(List<JsonAsserter> asserters, String executionResult) {
-
-        List<AssertionReport> failedReports = new ArrayList<>();
-
-        asserters.forEach(asserter -> {
-
-            final AssertionReport assertionReport = asserter.assertWithJson(executionResult);
-
-            if (!assertionReport.matches()) {
-
-                failedReports.add(assertionReport);
-
-            }
-        });
-
-        return failedReports;
-    }
-
-    private void loadAnnotatedHostProperties() {
-        try {
-            properties.load(getClass().getClassLoader().getResourceAsStream(hostFileName));
-        } catch (IOException e) {
-            LOGGER.error("Problem encountered while accessing annotated host properties file '" + hostFileName + "'");
-            throw new RuntimeException(e);
-        }
-
-        properties.keySet().stream().forEach(thisKey -> {
-            propertyKeys.add(thisKey.toString());
-        });
-    }
-
-    private boolean isPropertyKey(String runTimeToken) {
-        return propertyKeys.contains(runTimeToken);
-    }
-    
-    private LocalDateTime parseLocalDateTime (String value){ 	
-    	return LocalDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME);
-    }
-}
+/*
+ * Copyright (C) 2014 jApps Ltd and
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jsmart.zerocode.core.engine.preprocessor;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import com.jayway.jsonpath.JsonPath;
+
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.jsmart.zerocode.core.domain.reports.LocalDateTimeDeserializer;
+import org.jsmart.zerocode.core.engine.assertion.*;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+import static java.lang.String.format;
+import static org.apache.commons.lang.StringEscapeUtils.escapeJava;
+import static org.jsmart.zerocode.core.utils.TokenUtils.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
+
+    private static final org.slf4j.Logger LOGGER = getLogger(ZeroCodeJsonTestProcesorImpl.class);
+
+    final List<String> propertyKeys = new ArrayList<>();
+    final Properties properties = new Properties();
+
+    // -----------------------
+    // Assertion place holders
+    // -----------------------
+    public static final String ASSERT_VALUE_NOT_NULL = "$NOT.NULL";
+    public static final String ASSERT_VALUE_NULL = "$NULL";
+    public static final String ASSERT_VALUE_EMPTY_ARRAY = "$[]";
+    public static final String ASSERT_PATH_SIZE = ".SIZE";
+    public static final String ASSERT_VALUE_CONTAINS_STRING = "$CONTAINS.STRING:";
+    public static final String ASSERT_VALUE_MATCHES_STRING = "$MATCHES.STRING:";
+    public static final String ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE = "$CONTAINS.STRING.IGNORECASE:";
+    public static final String ASSERT_VALUE_EQUAL_TO_NUMBER = "$EQ.";
+    public static final String ASSERT_VALUE_NOT_EQUAL_TO_NUMBER = "$NOT.EQ.";
+    public static final String ASSERT_VALUE_GREATER_THAN = "$GT.";
+    public static final String ASSERT_VALUE_LESSER_THAN = "$LT.";
+    public static final String ASSERT_LOCAL_DATETIME_AFTER = "$LOCAL.DATETIME.AFTER:";
+    public static final String ASSERT_LOCAL_DATETIME_BEFORE = "$LOCAL.DATETIME.BEFORE:";
+    public static final String ASSERT_VALUE_ONE_OF = "$ONE.OF:";
+    public static final String ASSERT_PATH_VALUE_NODE = "$";
+    public static final String RAW_BODY = ".rawBody";
+
+    private final ObjectMapper mapper;
+    private final String hostFileName;
+
+    @Inject
+    public ZeroCodeJsonTestProcesorImpl(ObjectMapper mapper, @Named("HostFileName") String hostFileName) {
+        this.mapper = mapper;
+        this.hostFileName = hostFileName;
+        loadAnnotatedHostProperties();
+    }
+
+    @Override
+    public String resolveStringJson(String requestJsonOrAnyString, String scenarioStateJson) {
+        String resolvedFromTemplate = resolveKnownTokensAndProperties(requestJsonOrAnyString);
+        return resolveJsonPaths(resolvedFromTemplate, scenarioStateJson);
+    }
+
+    @Override
+    public String resolveKnownTokensAndProperties(String requestJsonOrAnyString) {
+        Map<String, Object> paramMap = new HashMap<>();
+
+        final List<String> testCaseTokens = getTestCaseTokens(requestJsonOrAnyString);
+
+        testCaseTokens.forEach(runTimeToken -> {
+            populateParamMap(paramMap, runTimeToken);
+
+            if (isPropertyKey(runTimeToken)) {
+                paramMap.put(runTimeToken, properties.get(runTimeToken));
+            }
+
+        });
+
+        StrSubstitutor sub = new StrSubstitutor(paramMap);
+
+        return sub.replace(requestJsonOrAnyString);
+    }
+
+    @Override
+    public String resolveJsonPaths(String jsonString, String scenarioState) {
+        List<String> jsonPaths = getAllJsonPathTokens(jsonString);
+        Map<String, String> paramMap = new HashMap<>();
+
+        jsonPaths.forEach(thisPath -> {
+            try {
+
+                if (thisPath.endsWith(RAW_BODY)) {
+                    /**
+                     * In case the rawBody is used anywhere in the steps as $.step_name.response.rawBody,
+                     * then it must be escaped as the content was not a simple JSON string to be able
+                     * to convert to json. Hence without throwing exception, treat as string content.
+                     *
+                     * Use escapeJava, do not use escapeJavaScript, as escapeJavaScript also escapes single quotes
+                     * which in turn throws Jackson Exception
+                     */
+                    String escapedString = escapeJava(JsonPath.read(scenarioState, thisPath));
+                    paramMap.put(thisPath, escapedString);
+
+                } else {
+                    // if it is a json block/node or array, this return value is LinkedHashMap.
+                    if (JsonPath.read(scenarioState, thisPath) instanceof LinkedHashMap) {
+                        final String pathValue = mapper.writeValueAsString(JsonPath.read(scenarioState, thisPath));
+                        String escapedPathValue = escapeJava(pathValue);
+                        paramMap.put(thisPath, escapedPathValue);
+
+                    } else {
+                        // Usual flow
+                        paramMap.put(thisPath, JsonPath.read(scenarioState, thisPath));
+
+                    }
+
+                }
+
+            } catch (Exception e) {
+                throw new RuntimeException("\nJSON:" + jsonString + "\nPossibly comments in the JSON found or bad JSON path found: " + thisPath + ", Details: " + e);
+            }
+        });
+
+        StrSubstitutor sub = new StrSubstitutor(paramMap);
+
+        return sub.replace(jsonString);
+    }
+
+    @Override
+    public List<String> getAllJsonPathTokens(String requestJsonAsString) {
+        List<String> jsonPaths = new ArrayList<>();
+
+        final List<String> allTokens = getTestCaseTokens(requestJsonAsString);
+        allTokens.forEach(thisToken -> {
+            if (thisToken.startsWith("$.")) {
+                jsonPaths.add(thisToken);
+            }
+        });
+
+        return jsonPaths;
+    }
+
+    @Override
+    public List<JsonAsserter> createAssertersFrom(String resolvedAssertionJson) {
+        List<JsonAsserter> asserters = new ArrayList<>();
+        try {
+            JsonNode jsonNode = mapper.readTree(resolvedAssertionJson);
+
+            Map<String, Object> createFieldsKeyValuesMap = createAssertionKV(jsonNode, "$.");
+
+            int i = 1;
+            for (Map.Entry<String, Object> entry : createFieldsKeyValuesMap.entrySet()) {
+                String path = entry.getKey();
+                Object value = entry.getValue();
+
+                JsonAsserter asserter;
+                if (ASSERT_VALUE_NOT_NULL.equals(value)) {
+                    asserter = new FieldIsNotNullAsserter(path);
+                } else if (ASSERT_VALUE_NULL.equals(value)) {
+                    asserter = new FieldIsNullAsserter(path);
+                } else if (ASSERT_VALUE_EMPTY_ARRAY.equals(value)) {
+                    asserter = new ArrayIsEmptyAsserter(path);
+                } else if (path.endsWith(ASSERT_PATH_SIZE)) {
+                    path = path.substring(0, path.length() - ASSERT_PATH_SIZE.length());
+                    if (value instanceof Number) {
+                        asserter = new ArraySizeAsserter(path, ((Integer) value).intValue());
+                    } else if (value instanceof String) {
+                        asserter = new ArraySizeAsserter(path, (String) value);
+                    } else {
+                        throw new RuntimeException(format("Oops! Unsupported value for .SIZE: %s", value));
+                    }
+                } else if (value instanceof String && ((String) value).startsWith(ASSERT_VALUE_CONTAINS_STRING)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_CONTAINS_STRING.length());
+                    asserter = new FieldHasSubStringValueAsserter(path, expected);
+                } else if (value instanceof String && ((String) value).startsWith(ASSERT_VALUE_MATCHES_STRING)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_MATCHES_STRING.length());
+                    asserter = new FieldMatchesRegexPatternAsserter(path, expected);
+                } else if (value instanceof String && ((String) value).startsWith(ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE.length());
+                    asserter = new FieldHasSubStringIgnoreCaseValueAsserter(path, expected);
+                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_EQUAL_TO_NUMBER)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_EQUAL_TO_NUMBER.length());
+                    asserter = new FieldHasEqualNumberValueAsserter(path, new BigDecimal(expected));
+                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_NOT_EQUAL_TO_NUMBER)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_NOT_EQUAL_TO_NUMBER.length());
+                    asserter = new FieldHasInEqualNumberValueAsserter(path, new BigDecimal(expected));
+                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_GREATER_THAN)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_GREATER_THAN.length());
+                    asserter = new FieldHasGreaterThanValueAsserter(path, new BigDecimal(expected));
+                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_LESSER_THAN)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_LESSER_THAN.length());
+                    asserter = new FieldHasLesserThanValueAsserter(path, new BigDecimal(expected));
+                } else if (value instanceof String && (value.toString()).startsWith(ASSERT_LOCAL_DATETIME_AFTER)) {
+                    String expected = ((String) value).substring(ASSERT_LOCAL_DATETIME_AFTER.length());
+                    asserter = new FieldHasDateAfterValueAsserter(path, parseLocalDateTime(expected));
+                }else if (value instanceof String && (value.toString()).startsWith(ASSERT_LOCAL_DATETIME_BEFORE)) {
+                    String expected = ((String) value).substring(ASSERT_LOCAL_DATETIME_BEFORE.length());
+                    asserter = new FieldHasDateBeforeValueAsserter(path, parseLocalDateTime(expected));
+                }else if (value instanceof String && (value.toString()).startsWith(ASSERT_VALUE_ONE_OF)) {
+                    String expected = ((String) value).substring(ASSERT_VALUE_ONE_OF.length());
+                    asserter = new FieldIsOneOfValueAsserter(path, expected);
+                }
+                else {
+                    asserter = new FieldHasExactValueAsserter(path, value);
+                }
+
+                asserters.add(asserter);
+            }
+        } catch (IOException parEx) {
+            throw new RuntimeException(parEx);
+        }
+
+        return asserters;
+    }
+
+    private Map<String, Object> createAssertionKV(JsonNode jsonNode, String pathDslPrefix) {
+        HashMap<String, Object> resultMap = new HashMap<String, Object>();
+
+        if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) {
+            jsonNode.fieldNames().forEachRemaining(fieldName -> {
+                String qualifiedName = pathDslPrefix + fieldName;
+                JsonNode thisNode = jsonNode.get(fieldName);
+
+                if (thisNode.isValueNode()) {
+                    Object value = convertJsonTypeToJavaType(jsonNode.get(fieldName));
+                    resultMap.put(qualifiedName, value);
+
+                } else {
+                    String newPrefix = qualifiedName + ".";
+                    resultMap.putAll(createAssertionKV(thisNode, newPrefix));
+
+                }
+            });
+
+        } else if (jsonNode.getNodeType().equals(JsonNodeType.ARRAY)) {
+            int i = 0;
+            final Iterator<JsonNode> arrayIterator = jsonNode.elements();
+            while (arrayIterator.hasNext()) {
+                final JsonNode thisElementValue = arrayIterator.next();
+                String elementName = String.format("%s[%d]", pathDslPrefix.substring(0, pathDslPrefix.lastIndexOf('.')), i++);
+
+                if (thisElementValue.isValueNode()) {
+                    Object value = convertJsonTypeToJavaType(thisElementValue);
+                    resultMap.put(elementName, value);
+
+                } else {
+                    String newPrefix = elementName + ".";
+                    resultMap.putAll(createAssertionKV(thisElementValue, newPrefix));
+
+                }
+            }
+        }
+        /*
+         * This is useful when only value is present without a key
+         * i.e. still a valid JSON even if it doesnt start-end with a '{'
+         */
+        else if (jsonNode.isValueNode()) {
+            Object value = convertJsonTypeToJavaType(jsonNode);
+            resultMap.put("$", value);
+
+        } else {
+            throw new RuntimeException(format("Oops! Unsupported JSON Type: %s", jsonNode.getClass().getName()));
+
+        }
+
+        return resultMap;
+    }
+
+    private Object convertJsonTypeToJavaType(JsonNode jsonNode) {
+        if (jsonNode.isValueNode()) {
+            if (jsonNode.isInt()) {
+                return jsonNode.asInt();
+
+            } else if (jsonNode.isTextual()) {
+                return jsonNode.asText();
+
+            } else if (jsonNode.isBoolean()) {
+                return jsonNode.asBoolean();
+
+            } else if (jsonNode.isLong()) {
+                return jsonNode.asLong();
+
+            } else if (jsonNode.isDouble()) {
+                return jsonNode.asDouble();
+
+            } else if (jsonNode.isNull()) {
+                return null;
+
+            } else {
+                throw new RuntimeException(format("Oops! Unsupported JSON primitive to Java : %s by the framework", jsonNode.getClass().getName()));
+            }
+        } else {
+            throw new RuntimeException(format("Unsupported JSON Type: %s", jsonNode.getClass().getName()));
+        }
+    }
+
+    @Override
+    public List<AssertionReport> assertAllAndReturnFailed(List<JsonAsserter> asserters, String executionResult) {
+
+        List<AssertionReport> failedReports = new ArrayList<>();
+
+        asserters.forEach(asserter -> {
+
+            final AssertionReport assertionReport = asserter.assertWithJson(executionResult);
+
+            if (!assertionReport.matches()) {
+
+                failedReports.add(assertionReport);
+
+            }
+        });
+
+        return failedReports;
+    }
+
+    private void loadAnnotatedHostProperties() {
+        try {
+            properties.load(getClass().getClassLoader().getResourceAsStream(hostFileName));
+        } catch (IOException e) {
+            LOGGER.error("Problem encountered while accessing annotated host properties file '" + hostFileName + "'");
+            throw new RuntimeException(e);
+        }
+
+        properties.keySet().stream().forEach(thisKey -> {
+            propertyKeys.add(thisKey.toString());
+        });
+    }
+
+    private boolean isPropertyKey(String runTimeToken) {
+        return propertyKeys.contains(runTimeToken);
+    }
+    
+    private LocalDateTime parseLocalDateTime (String value){ 	
+    	return LocalDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME);
+    }
+}
diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImplTest.java
index 2c6be922..052248f9 100644
--- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImplTest.java
+++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImplTest.java
@@ -1,848 +1,1009 @@
-package org.jsmart.zerocode.core.engine.preprocessor;
-
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.jayway.jsonpath.JsonPath;
-import org.jsmart.simulator.main.SimpleRestJsonSimulatorsMain;
-import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
-import org.jsmart.zerocode.core.domain.ScenarioSpec;
-import org.jsmart.zerocode.core.engine.assertion.AssertionReport;
-import org.jsmart.zerocode.core.engine.assertion.JsonAsserter;
-import org.jsmart.zerocode.core.engine.executor.JsonServiceExecutorImpl;
-import org.jsmart.zerocode.core.utils.SmartUtils;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertThat;
-
-public class ZeroCodeJsonTestProcesorImplTest {
-    JsonServiceExecutorImpl jsonServiceExecutor;
-    Injector injector;
-    SmartUtils smartUtils;
-    SimpleRestJsonSimulatorsMain simulator ;
-
-    ZeroCodeJsonTestProcesor jsonPreProcessor;
-
-    @Before
-    public void setUpStuff() throws Exception {
-        String serverEnvFileName = "config_hosts_test.properties";
-        injector = Guice.createInjector(new ApplicationMainModule(serverEnvFileName));
-        smartUtils = injector.getInstance(SmartUtils.class);
-        jsonPreProcessor = new ZeroCodeJsonTestProcesorImpl(smartUtils.getMapper(), serverEnvFileName);
-    }
-
-    @Test
-    public void willEvaluatePlaceHolder() throws Exception {
-
-        String aString = "Hello_${WORLD}";
-        List<String> placeHolders = getTestCaseTokens(aString);
-        assertThat(placeHolders.size(), is(1));
-        assertThat(placeHolders.get(0), is("WORLD"));
-
-        aString = "Hello_${$.step_name}";
-        placeHolders = getTestCaseTokens(aString);
-        assertThat(placeHolders.size(), is(1));
-        assertThat(placeHolders.get(0), is("$.step_name"));
-
-    }
-    
-    @Test
-    public void willResolveWithParamMap() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("09_test_engine/01_request_with_place_holders.json", ScenarioSpec.class);
-        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
-
-        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
-
-        String lastName = JsonPath.read(resolvedRequestJson, "$.body.Customer.lastName");
-        String nickName = JsonPath.read(resolvedRequestJson, "$.body.Customer.nickName");
-
-        assertNotEquals(lastName, nickName);
-    }
-
-    @Test
-    public void willCaptureAllPlaceHolders() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("09_test_engine/01_request_with_place_holders.json", ScenarioSpec.class);
-        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
-
-        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
-        assertThat(placeHolders.size(), is(4));
-
-        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
-        assertThat(resolvedRequestJson, containsString("\"staticName\":\"abcde\""));
-
-        String specAsString = smartUtils.getJsonDocumentAsString("09_test_engine/01_request_with_place_holders.json");
-        final String resolvedSpecString = jsonPreProcessor.resolveStringJson(specAsString, specAsString);
-        assertThat(resolvedSpecString, containsString("\"url\": \"/persons/abc\""));
-    }
-
-    @Test
-    public void willResolveJsonPathOfJayWay() throws Exception {
-        String specAsString = smartUtils.getJsonDocumentAsString("09_test_engine/01_request_with_place_holders.json");
-
-        final List<String> jsonPaths = jsonPreProcessor.getAllJsonPathTokens(specAsString);
-        assertThat(jsonPaths.size(), is(2));
-
-        final String resolvedSpecWithPaths = jsonPreProcessor.resolveStringJson(specAsString, specAsString);
-        assertThat(resolvedSpecWithPaths, containsString("\"staticName\": \"abcde\""));
-
-        //final String resolvedSpecResolvedPaths = jsonPreProcessor.resolveJsonPaths(resolvedSpecWithPaths);
-        assertThat(resolvedSpecWithPaths, containsString("\"actualName\": \"${STATIC.ALPHABET:5}\""));
-        assertThat(resolvedSpecWithPaths, containsString("\"actualNameSize\": \"2\""));
-    }
-
-    @Test
-    public void willResolveJsonPathOfJayWayWith_SuppliedScenarioState() throws Exception {
-        String specAsString = smartUtils.getJsonDocumentAsString("09_test_engine/02_1_two_requests_with_json_path_assertion.json");
-
-        final List<String> jsonPaths = jsonPreProcessor.getAllJsonPathTokens(specAsString);
-        assertThat(jsonPaths.size(), is(3));
-
-        String scenarioState = "{\n" +
-                "    \"step1\": {\n" +
-                "        \"request\": {\n" +
-                "            \"body\": {\n" +
-                "                \"customer\": {\n" +
-                "                    \"firstName\": \"FIRST_NAME\",\n" +
-                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
-                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
-                "                }\n" +
-                "            }\n" +
-                "        },\n" +
-                "        \"response\": {\n" +
-                "            \"id\": 10101\n" +
-                "        }\n" +
-                "    }\n" +
-                "}";
-        final String resolvedSpecWithPaths = jsonPreProcessor.resolveStringJson(specAsString, scenarioState);
-        assertThat(resolvedSpecWithPaths, containsString("\"staticName\": \"abcde\""));
-        assertThat(resolvedSpecWithPaths, containsString("\"firstName\": \"FIRST_NAME\""));
-        assertThat(resolvedSpecWithPaths, containsString("\"firstName2\": \"FIRST_NAME\""));
-        assertThat(resolvedSpecWithPaths, containsString("\"actualName\": \"ANOTHER_NAME\""));
-        assertThat(resolvedSpecWithPaths, containsString("\"noOfAddresses\": \"2\""));
-
-    }
-
-    @Test
-    public void willResolveJsonPathOfJayWayFor_AssertionSection() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("09_test_engine/02_1_two_requests_with_json_path_assertion.json", ScenarioSpec.class);
-
-        // Get the 2nd step
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(1).getAssertions().toString();
-        String scenarioState = "{\n" +
-                "    \"step1\": {\n" +
-                "        \"request\": {\n" +
-                "            \"body\": {\n" +
-                "                \"customer\": {\n" +
-                "                    \"firstName\": \"FIRST_NAME\",\n" +
-                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
-                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
-                "                }\n" +
-                "            }\n" +
-                "        },\n" +
-                "        \"response\": {\n" +
-                "            \"id\": 10101\n" +
-                "        }\n" +
-                "    }\n" +
-                "}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, scenarioState);
-        assertThat(resolvedAssertions, containsString("\"actualName\":\"ANOTHER_NAME\""));
-
-        // start assertion
-        String sapmleExecutionResult =
-                smartUtils.getJsonDocumentAsString("09_test_engine/02_2_sample_resolved_execution_response.json");
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(17));
-
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, sapmleExecutionResult);
-
-        System.out.println("###failedReports : " + failedReports);
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'NOT NULL'"));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'ANOTHER_NAME'"));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'NULL'"));
-        assertThat(failedReports.toString(), containsString("citizenship' with actual value '[{"));
-        assertThat(failedReports.toString(), containsString("personalities' with actual value 'null'"));
-        assertThat(failedReports.toString(), containsString("did not match the expected value '[]'"));
-        assertThat(failedReports.toString(), not(containsString("pastActivities")));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'Array of size 5'"));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'Array of size 4'"));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'containing sub-string:DaddyWithMac'"));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'Greater Than:499'"));
-        assertThat(failedReports.toString(), containsString("'null' did not match the expected value 'Greater Than:388'"));
-        assertThat(failedReports.toString(), containsString("actual value '1400' did not match the expected value 'Lesser Than:1300'"));
-        assertThat(failedReports.size(), is(11));
-
-    }
-
-    @Test
-    public void willResolveTextNodeFor_Assertion() throws Exception {
-
-        final String assertionsSectionTextNodeAsString = "\"id-generated-0101\"";
-
-        String scenarioState = "{\n" +
-                "    \"step1\": {\n" +
-                "        \"request\": {\n" +
-                "            \"body\": {\n" +
-                "                \"customer\": {\n" +
-                "                    \"firstName\": \"FIRST_NAME\",\n" +
-                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
-                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
-                "                }\n" +
-                "            }\n" +
-                "        },\n" +
-                "        \"response\": \"id-generated-0101-aga-baga\"" + //<--- In this case this is not relevant as this path is not used
-                "    }\n" +
-                "}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionTextNodeAsString, scenarioState);
-        assertThat(resolvedAssertions, containsString("\"id-generated-0101\""));
-
-        // start assertion
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(1));
-
-        String sampleExecutionResult = "\"id-generated-0101-XY\"";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, sampleExecutionResult);
-
-        System.out.println("###failedReports : " + failedReports);
-        assertThat(failedReports.toString(), containsString("'$' with actual value 'id-generated-0101-XY' did not match the expected value 'id-generated-0101'"));
-        assertThat(failedReports.size(), is(1));
-    }
-
-    @Test
-    public void willResolveIntegerNodeFor_Assertion() throws Exception {
-
-        final Integer assertionsSectionInt = 1099;
-
-        String scenarioState = "{\n" +
-                "    \"step1\": {\n" +
-                "        \"request\": {\n" +
-                "            \"body\": {\n" +
-                "                \"customer\": {\n" +
-                "                    \"firstName\": \"FIRST_NAME\",\n" +
-                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
-                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
-                "                }\n" +
-                "            }\n" +
-                "        },\n" +
-                "        \"response\": 300000" + //<--- In this case this is not relevant as this path is not used
-                "    }\n" +
-                "}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionInt.toString(), scenarioState);
-        assertThat(resolvedAssertions, containsString("1099"));
-
-        // start assertion
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(1));
-
-        Integer sampleExecutionResult = 1077;
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, sampleExecutionResult.toString());
-
-        System.out.println("###failedReports : " + failedReports);
-        assertThat(failedReports.toString(), containsString("'$' with actual value '1077' did not match the expected value '1099'"));
-        assertThat(failedReports.size(), is(1));
-    }
-
-    @Test
-    public void testLocalDate_formatter() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "15_localdatetime/00_local_date_time_place_holders_unit_test.json",
-                ScenarioSpec.class
-        );
-
-        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
-
-        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
-        assertThat(placeHolders.size(), is(2));
-
-        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
-        assertThat(resolvedRequestJson.indexOf("LOCAL.DATE.TODAY:"), is(-1));
-        assertThat(resolvedRequestJson.indexOf("${LOCAL.DATE.TODAY:yyyy}"), is(-1));
-    }
-
-    @Test
-    public void testLocalDateTime_formatter() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "15_localdatetime/00_local_date_time_place_holders_unit_test.json",
-                ScenarioSpec.class
-        );
-
-        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
-
-        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
-        assertThat(placeHolders.size(), is(2));
-
-        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
-        assertThat(resolvedRequestJson.indexOf("LOCAL.DATETIME.NOW:"), is(-1));
-    }
-
-    @Test
-    public void testRandom_UUID() throws Exception {
-
-        final String requestJsonAsString = "{\n" +
-                "\t\"onlineOrderId\": \"${RANDOM.UUID}\"\n" +
-                "}";
-
-        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
-        assertThat(placeHolders.size(), is(1));
-
-        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
-        assertThat(resolvedRequestJson.indexOf("RANDOM.UUID"), is(-1));
-
-        final HashMap<String, String> hashMap = smartUtils.getMapper().readValue(resolvedRequestJson, HashMap.class);
-
-        assertThat(hashMap.get("onlineOrderId").length(), is(36)); //"onlineOrderId": "48c3b4ff-5078-40bb-8d62-11abcbdef5b3"
-    }
-
-    @Test
-    public void testIgnoreCaseWith_containsNoMatch() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("18_ignore_case/test_string_match_withIgnoring_case.json", ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"name\":\"$CONTAINS.STRING.IGNORECASE:CReASY\"}}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "  \"status\": 201,\n" +
-                "  \"body\": {\n" +
-                "    \"name\": \"Hello CreXasy\"\n" +
-                "  }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.toString(), containsString("did not match the expected value 'containing sub-string with ignoring case:"));
-    }
-
-    @Test
-    public void testIgnoreCaseWith_containsMatch() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("18_ignore_case/test_string_match_withIgnoring_case.json", ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"name\":\"$CONTAINS.STRING.IGNORECASE:CReASY\"}}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "  \"status\": 201,\n" +
-                "  \"body\": {\n" +
-                "    \"name\": \"Hello Creasy\"\n" +
-                "  }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testString_regexMatch() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "regex_match/string_matches_regex_test.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"dob\":\"$MATCHES.STRING:\\\\d{4}-\\\\d{2}-\\\\d{2}\"}}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "  \"status\": 201,\n" +
-                "  \"body\": {\n" +
-                "    \"dob\": \"2018-06-26\"\n" +
-                "  }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testArraySize_numberOnly() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_number_only_test.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":2}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testArraySize_numberOnlyNegative() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_number_only_test.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":2}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-    }
-
-    @Test
-    public void testArraySize_expressionGT() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_GT.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$GT.1\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testArraySize_expressionFailTest() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_fail_test_GT.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$GT.5\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $GT.5'"));
-    }
-
-    @Test
-    public void testArraySize_expressionLT() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_LT.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$LT.3\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testArraySize_expressionFailLT() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_fail_LT.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$LT.1\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $LT.1'"));
-    }
-
-    @Test
-    public void testArraySize_expressionEQ() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_EQ.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$EQ.2\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testArraySize_expressionFailEQ() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_fail_EQ.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$EQ.3\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $EQ.3'"));
-    }
-
-    @Test
-    public void testArraySize_expressionNotEQ() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_NotEQ.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$NOT.EQ.3\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(0));
-    }
-
-    @Test
-    public void testArraySize_expressionFailNotEQ() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "array_size/array_size_expresssion_test_fail_NotEQ.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$NOT.EQ.2\"}"));
-
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "    \"status\": 201,\n" +
-                "    \"body\": {\n" +
-                "        \"persons\": [\n" +
-                "            {\n" +
-                "                \"name\": \"Tom\"\n" +
-                "            },\n" +
-                "            {\n" +
-                "                \"name\": \"Mady\"\n" +
-                "            }\n" +
-                "        ]\n" +
-                "    }\n" +
-                "}";
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $NOT.EQ.2'"));
-    }
-    
-    @Test
-    public void testDateAfterBefore_both() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "date_after_before/dateAfterBefore_test_both.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.BEFORE:2015-09-14T09:49:34.000Z\","));
-        assertThat(resolvedAssertions, containsString("\"endDateTime\":\"$LOCAL.DATETIME.AFTER:2015-09-14T09:49:34.000Z\""));
-        
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(3));
-
-        String mockTestResponse = "{\n" +
-                "	\"status\": 200,\n" +
-                "	\"body\": {\n" +
-                "	    \"projectDetails\": {\n" +
-                "            \"startDateTime\": \"2014-09-14T09:49:34.000Z\",\n" +
-                "            \"endDateTime\": \"2016-09-14T09:49:34.000Z\"\n" +
-                "        }\n" +
-                "    }\n" +
-                "}";
-    
-        
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-        assertThat(failedReports.size(), is(0));
-    }
-    
-    @Test
-    public void testDateAfterBefore_fail_both() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "date_after_before/dateAfterBefore_test_fail_both.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.BEFORE:2016-09-14T09:49:34.000Z\","));
-        assertThat(resolvedAssertions, containsString("\"endDateTime\":\"$LOCAL.DATETIME.AFTER:2019-09-14T09:49:34.000Z\""));
-        
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(3));
-
-        String mockTestResponse = "{\n" +
-                "	\"status\": 200,\n" +
-                "	\"body\": {\n" +
-                "	    \"projectDetails\": {\n" +
-                "	            \"startDateTime\": \"2017-04-14T11:49:56.000Z\",\n" +
-                "	            \"endDateTime\": \"2018-11-12T09:39:34.000Z\"\n" +
-                "        }\n" +
-                "    }\n" +
-                "}";
-    
-        
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(2));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.projectDetails.startDateTime' with actual value '2017-04-14T11:49:56.000Z' "
-                		+ "did not match the expected value 'Date Before:2016-09-14T09:49:34'"));
-        assertThat(failedReports.get(1).toString(),
-                is("Assertion path '$.body.projectDetails.endDateTime' with actual value '2018-11-12T09:39:34.000Z' "
-                		+ "did not match the expected value 'Date After:2019-09-14T09:49:34'"));
-    }
-    
-    @Test
-    public void testDateAfterBefore_fail_afterSameDate() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "date_after_before/dateAfterBefore_test_fail_afterSameDate.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.AFTER:2015-09-14T09:49:34.000Z\""));
-        
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "	\"status\": 200,\n" +
-                "	\"body\": {\n" +
-                "	    \"projectDetails\": {\n" +
-                "	            \"startDateTime\": \"2015-09-14T09:49:34.000Z\",\n" +
-                "        }\n" +
-                "    }\n" +
-                "}";
-    
-        
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.projectDetails.startDateTime' with actual value '2015-09-14T09:49:34.000Z' "
-                		+ "did not match the expected value 'Date After:2015-09-14T09:49:34'"));
-    }
-    
-    @Test
-    public void testDateAfterBefore_fail_beforeSameDate() throws Exception {
-        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
-                "date_after_before/dateAfterBefore_test_fail_beforeSameDate.json",
-                ScenarioSpec.class);
-
-        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
-        String mockScenarioState = "{}";
-
-        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
-        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.BEFORE:2015-09-14T09:49:34.000Z\""));
-        
-        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
-        assertThat(asserters.size(), is(2));
-
-        String mockTestResponse = "{\n" +
-                "	\"status\": 200,\n" +
-                "	\"body\": {\n" +
-                " 		\"projectDetails\": {\n" +
-                "			\"startDateTime\": \"2015-09-14T09:49:34.000Z\",\n" +
-                "		}\n" +
-                "	}\n" +
-                "}";
-    
-        
-        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
-
-        assertThat(failedReports.size(), is(1));
-        assertThat(failedReports.get(0).toString(),
-                is("Assertion path '$.body.projectDetails.startDateTime' with actual value '2015-09-14T09:49:34.000Z' "
-                		+ "did not match the expected value 'Date Before:2015-09-14T09:49:34'"));
-    }
+package org.jsmart.zerocode.core.engine.preprocessor;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.jayway.jsonpath.JsonPath;
+import org.jsmart.simulator.main.SimpleRestJsonSimulatorsMain;
+import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
+import org.jsmart.zerocode.core.domain.ScenarioSpec;
+import org.jsmart.zerocode.core.engine.assertion.AssertionReport;
+import org.jsmart.zerocode.core.engine.assertion.JsonAsserter;
+import org.jsmart.zerocode.core.engine.executor.JsonServiceExecutorImpl;
+import org.jsmart.zerocode.core.utils.SmartUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+
+public class ZeroCodeJsonTestProcesorImplTest {
+    JsonServiceExecutorImpl jsonServiceExecutor;
+    Injector injector;
+    SmartUtils smartUtils;
+    SimpleRestJsonSimulatorsMain simulator ;
+
+    ZeroCodeJsonTestProcesor jsonPreProcessor;
+
+    @Before
+    public void setUpStuff() throws Exception {
+        String serverEnvFileName = "config_hosts_test.properties";
+        injector = Guice.createInjector(new ApplicationMainModule(serverEnvFileName));
+        smartUtils = injector.getInstance(SmartUtils.class);
+        jsonPreProcessor = new ZeroCodeJsonTestProcesorImpl(smartUtils.getMapper(), serverEnvFileName);
+    }
+
+    @Test
+    public void willEvaluatePlaceHolder() throws Exception {
+
+        String aString = "Hello_${WORLD}";
+        List<String> placeHolders = getTestCaseTokens(aString);
+        assertThat(placeHolders.size(), is(1));
+        assertThat(placeHolders.get(0), is("WORLD"));
+
+        aString = "Hello_${$.step_name}";
+        placeHolders = getTestCaseTokens(aString);
+        assertThat(placeHolders.size(), is(1));
+        assertThat(placeHolders.get(0), is("$.step_name"));
+
+    }
+    
+    @Test
+    public void willResolveWithParamMap() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("09_test_engine/01_request_with_place_holders.json", ScenarioSpec.class);
+        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
+
+        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
+
+        String lastName = JsonPath.read(resolvedRequestJson, "$.body.Customer.lastName");
+        String nickName = JsonPath.read(resolvedRequestJson, "$.body.Customer.nickName");
+
+        assertNotEquals(lastName, nickName);
+    }
+
+    @Test
+    public void willCaptureAllPlaceHolders() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("09_test_engine/01_request_with_place_holders.json", ScenarioSpec.class);
+        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
+
+        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
+        assertThat(placeHolders.size(), is(4));
+
+        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
+        assertThat(resolvedRequestJson, containsString("\"staticName\":\"abcde\""));
+
+        String specAsString = smartUtils.getJsonDocumentAsString("09_test_engine/01_request_with_place_holders.json");
+        final String resolvedSpecString = jsonPreProcessor.resolveStringJson(specAsString, specAsString);
+        assertThat(resolvedSpecString, containsString("\"url\": \"/persons/abc\""));
+    }
+
+    @Test
+    public void willResolveJsonPathOfJayWay() throws Exception {
+        String specAsString = smartUtils.getJsonDocumentAsString("09_test_engine/01_request_with_place_holders.json");
+
+        final List<String> jsonPaths = jsonPreProcessor.getAllJsonPathTokens(specAsString);
+        assertThat(jsonPaths.size(), is(2));
+
+        final String resolvedSpecWithPaths = jsonPreProcessor.resolveStringJson(specAsString, specAsString);
+        assertThat(resolvedSpecWithPaths, containsString("\"staticName\": \"abcde\""));
+
+        //final String resolvedSpecResolvedPaths = jsonPreProcessor.resolveJsonPaths(resolvedSpecWithPaths);
+        assertThat(resolvedSpecWithPaths, containsString("\"actualName\": \"${STATIC.ALPHABET:5}\""));
+        assertThat(resolvedSpecWithPaths, containsString("\"actualNameSize\": \"2\""));
+    }
+
+    @Test
+    public void willResolveJsonPathOfJayWayWith_SuppliedScenarioState() throws Exception {
+        String specAsString = smartUtils.getJsonDocumentAsString("09_test_engine/02_1_two_requests_with_json_path_assertion.json");
+
+        final List<String> jsonPaths = jsonPreProcessor.getAllJsonPathTokens(specAsString);
+        assertThat(jsonPaths.size(), is(3));
+
+        String scenarioState = "{\n" +
+                "    \"step1\": {\n" +
+                "        \"request\": {\n" +
+                "            \"body\": {\n" +
+                "                \"customer\": {\n" +
+                "                    \"firstName\": \"FIRST_NAME\",\n" +
+                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
+                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"response\": {\n" +
+                "            \"id\": 10101\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+        final String resolvedSpecWithPaths = jsonPreProcessor.resolveStringJson(specAsString, scenarioState);
+        assertThat(resolvedSpecWithPaths, containsString("\"staticName\": \"abcde\""));
+        assertThat(resolvedSpecWithPaths, containsString("\"firstName\": \"FIRST_NAME\""));
+        assertThat(resolvedSpecWithPaths, containsString("\"firstName2\": \"FIRST_NAME\""));
+        assertThat(resolvedSpecWithPaths, containsString("\"actualName\": \"ANOTHER_NAME\""));
+        assertThat(resolvedSpecWithPaths, containsString("\"noOfAddresses\": \"2\""));
+
+    }
+
+    @Test
+    public void willResolveJsonPathOfJayWayFor_AssertionSection() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("09_test_engine/02_1_two_requests_with_json_path_assertion.json", ScenarioSpec.class);
+
+        // Get the 2nd step
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(1).getAssertions().toString();
+        String scenarioState = "{\n" +
+                "    \"step1\": {\n" +
+                "        \"request\": {\n" +
+                "            \"body\": {\n" +
+                "                \"customer\": {\n" +
+                "                    \"firstName\": \"FIRST_NAME\",\n" +
+                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
+                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"response\": {\n" +
+                "            \"id\": 10101\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, scenarioState);
+        assertThat(resolvedAssertions, containsString("\"actualName\":\"ANOTHER_NAME\""));
+
+        // start assertion
+        String sapmleExecutionResult =
+                smartUtils.getJsonDocumentAsString("09_test_engine/02_2_sample_resolved_execution_response.json");
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(17));
+
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, sapmleExecutionResult);
+
+        System.out.println("###failedReports : " + failedReports);
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'NOT NULL'"));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'ANOTHER_NAME'"));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'NULL'"));
+        assertThat(failedReports.toString(), containsString("citizenship' with actual value '[{"));
+        assertThat(failedReports.toString(), containsString("personalities' with actual value 'null'"));
+        assertThat(failedReports.toString(), containsString("did not match the expected value '[]'"));
+        assertThat(failedReports.toString(), not(containsString("pastActivities")));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'Array of size 5'"));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'Array of size 4'"));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'containing sub-string:DaddyWithMac'"));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'Greater Than:499'"));
+        assertThat(failedReports.toString(), containsString("'null' did not match the expected value 'Greater Than:388'"));
+        assertThat(failedReports.toString(), containsString("actual value '1400' did not match the expected value 'Lesser Than:1300'"));
+        assertThat(failedReports.size(), is(11));
+
+    }
+
+    @Test
+    public void willResolveTextNodeFor_Assertion() throws Exception {
+
+        final String assertionsSectionTextNodeAsString = "\"id-generated-0101\"";
+
+        String scenarioState = "{\n" +
+                "    \"step1\": {\n" +
+                "        \"request\": {\n" +
+                "            \"body\": {\n" +
+                "                \"customer\": {\n" +
+                "                    \"firstName\": \"FIRST_NAME\",\n" +
+                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
+                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"response\": \"id-generated-0101-aga-baga\"" + //<--- In this case this is not relevant as this path is not used
+                "    }\n" +
+                "}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionTextNodeAsString, scenarioState);
+        assertThat(resolvedAssertions, containsString("\"id-generated-0101\""));
+
+        // start assertion
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(1));
+
+        String sampleExecutionResult = "\"id-generated-0101-XY\"";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, sampleExecutionResult);
+
+        System.out.println("###failedReports : " + failedReports);
+        assertThat(failedReports.toString(), containsString("'$' with actual value 'id-generated-0101-XY' did not match the expected value 'id-generated-0101'"));
+        assertThat(failedReports.size(), is(1));
+    }
+
+    @Test
+    public void willResolveIntegerNodeFor_Assertion() throws Exception {
+
+        final Integer assertionsSectionInt = 1099;
+
+        String scenarioState = "{\n" +
+                "    \"step1\": {\n" +
+                "        \"request\": {\n" +
+                "            \"body\": {\n" +
+                "                \"customer\": {\n" +
+                "                    \"firstName\": \"FIRST_NAME\",\n" +
+                "                    \"staticName\": \"ANOTHER_NAME\",\n" +
+                "                    \"addresses\":[\"office-1\", \"home-2\"]\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"response\": 300000" + //<--- In this case this is not relevant as this path is not used
+                "    }\n" +
+                "}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionInt.toString(), scenarioState);
+        assertThat(resolvedAssertions, containsString("1099"));
+
+        // start assertion
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(1));
+
+        Integer sampleExecutionResult = 1077;
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, sampleExecutionResult.toString());
+
+        System.out.println("###failedReports : " + failedReports);
+        assertThat(failedReports.toString(), containsString("'$' with actual value '1077' did not match the expected value '1099'"));
+        assertThat(failedReports.size(), is(1));
+    }
+
+    @Test
+    public void testLocalDate_formatter() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "15_localdatetime/00_local_date_time_place_holders_unit_test.json",
+                ScenarioSpec.class
+        );
+
+        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
+
+        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
+        assertThat(placeHolders.size(), is(2));
+
+        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
+        assertThat(resolvedRequestJson.indexOf("LOCAL.DATE.TODAY:"), is(-1));
+        assertThat(resolvedRequestJson.indexOf("${LOCAL.DATE.TODAY:yyyy}"), is(-1));
+    }
+
+    @Test
+    public void testLocalDateTime_formatter() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "15_localdatetime/00_local_date_time_place_holders_unit_test.json",
+                ScenarioSpec.class
+        );
+
+        final String requestJsonAsString = scenarioSpec.getSteps().get(0).getRequest().toString();
+
+        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
+        assertThat(placeHolders.size(), is(2));
+
+        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
+        assertThat(resolvedRequestJson.indexOf("LOCAL.DATETIME.NOW:"), is(-1));
+    }
+
+    @Test
+    public void testRandom_UUID() throws Exception {
+
+        final String requestJsonAsString = "{\n" +
+                "\t\"onlineOrderId\": \"${RANDOM.UUID}\"\n" +
+                "}";
+
+        final List<String> placeHolders = getTestCaseTokens(requestJsonAsString);
+        assertThat(placeHolders.size(), is(1));
+
+        final String resolvedRequestJson = jsonPreProcessor.resolveStringJson(requestJsonAsString, requestJsonAsString);
+        assertThat(resolvedRequestJson.indexOf("RANDOM.UUID"), is(-1));
+
+        final HashMap<String, String> hashMap = smartUtils.getMapper().readValue(resolvedRequestJson, HashMap.class);
+
+        assertThat(hashMap.get("onlineOrderId").length(), is(36)); //"onlineOrderId": "48c3b4ff-5078-40bb-8d62-11abcbdef5b3"
+    }
+
+    @Test
+    public void testIgnoreCaseWith_containsNoMatch() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("18_ignore_case/test_string_match_withIgnoring_case.json", ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"name\":\"$CONTAINS.STRING.IGNORECASE:CReASY\"}}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "  \"status\": 201,\n" +
+                "  \"body\": {\n" +
+                "    \"name\": \"Hello CreXasy\"\n" +
+                "  }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.toString(), containsString("did not match the expected value 'containing sub-string with ignoring case:"));
+    }
+
+    @Test
+    public void testIgnoreCaseWith_containsMatch() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava("18_ignore_case/test_string_match_withIgnoring_case.json", ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"name\":\"$CONTAINS.STRING.IGNORECASE:CReASY\"}}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "  \"status\": 201,\n" +
+                "  \"body\": {\n" +
+                "    \"name\": \"Hello Creasy\"\n" +
+                "  }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testString_regexMatch() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "regex_match/string_matches_regex_test.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"dob\":\"$MATCHES.STRING:\\\\d{4}-\\\\d{2}-\\\\d{2}\"}}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "  \"status\": 201,\n" +
+                "  \"body\": {\n" +
+                "    \"dob\": \"2018-06-26\"\n" +
+                "  }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testArraySize_numberOnly() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_number_only_test.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":2}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testArraySize_numberOnlyNegative() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_number_only_test.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":2}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+    }
+
+    @Test
+    public void testArraySize_expressionGT() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_GT.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$GT.1\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testArraySize_expressionFailTest() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_fail_test_GT.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$GT.5\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $GT.5'"));
+    }
+
+    @Test
+    public void testArraySize_expressionLT() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_LT.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$LT.3\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testArraySize_expressionFailLT() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_fail_LT.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$LT.1\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $LT.1'"));
+    }
+
+    @Test
+    public void testArraySize_expressionEQ() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_EQ.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$EQ.2\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testArraySize_expressionFailEQ() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_fail_EQ.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$EQ.3\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $EQ.3'"));
+    }
+
+    @Test
+    public void testArraySize_expressionNotEQ() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_NotEQ.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$NOT.EQ.3\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+
+    @Test
+    public void testArraySize_expressionFailNotEQ() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "array_size/array_size_expresssion_test_fail_NotEQ.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("{\"persons.SIZE\":\"$NOT.EQ.2\"}"));
+
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 201,\n" +
+                "    \"body\": {\n" +
+                "        \"persons\": [\n" +
+                "            {\n" +
+                "                \"name\": \"Tom\"\n" +
+                "            },\n" +
+                "            {\n" +
+                "                \"name\": \"Mady\"\n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.persons' with actual value '2' did not match the expected value 'Array of size $NOT.EQ.2'"));
+    }
+    
+    @Test
+    public void testDateAfterBefore_both() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "date_after_before/dateAfterBefore_test_both.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.BEFORE:2015-09-14T09:49:34.000Z\","));
+        assertThat(resolvedAssertions, containsString("\"endDateTime\":\"$LOCAL.DATETIME.AFTER:2015-09-14T09:49:34.000Z\""));
+        
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(3));
+
+        String mockTestResponse = "{\n" +
+                "	\"status\": 200,\n" +
+                "	\"body\": {\n" +
+                "	    \"projectDetails\": {\n" +
+                "            \"startDateTime\": \"2014-09-14T09:49:34.000Z\",\n" +
+                "            \"endDateTime\": \"2016-09-14T09:49:34.000Z\"\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+    
+        
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+        assertThat(failedReports.size(), is(0));
+    }
+    
+    @Test
+    public void testDateAfterBefore_fail_both() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "date_after_before/dateAfterBefore_test_fail_both.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.BEFORE:2016-09-14T09:49:34.000Z\","));
+        assertThat(resolvedAssertions, containsString("\"endDateTime\":\"$LOCAL.DATETIME.AFTER:2019-09-14T09:49:34.000Z\""));
+        
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(3));
+
+        String mockTestResponse = "{\n" +
+                "	\"status\": 200,\n" +
+                "	\"body\": {\n" +
+                "	    \"projectDetails\": {\n" +
+                "	            \"startDateTime\": \"2017-04-14T11:49:56.000Z\",\n" +
+                "	            \"endDateTime\": \"2018-11-12T09:39:34.000Z\"\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+    
+        
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(2));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.projectDetails.startDateTime' with actual value '2017-04-14T11:49:56.000Z' "
+                		+ "did not match the expected value 'Date Before:2016-09-14T09:49:34'"));
+        assertThat(failedReports.get(1).toString(),
+                is("Assertion path '$.body.projectDetails.endDateTime' with actual value '2018-11-12T09:39:34.000Z' "
+                		+ "did not match the expected value 'Date After:2019-09-14T09:49:34'"));
+    }
+    
+    @Test
+    public void testDateAfterBefore_fail_afterSameDate() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "date_after_before/dateAfterBefore_test_fail_afterSameDate.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.AFTER:2015-09-14T09:49:34.000Z\""));
+        
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "	\"status\": 200,\n" +
+                "	\"body\": {\n" +
+                "	    \"projectDetails\": {\n" +
+                "	            \"startDateTime\": \"2015-09-14T09:49:34.000Z\",\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+    
+        
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.projectDetails.startDateTime' with actual value '2015-09-14T09:49:34.000Z' "
+                		+ "did not match the expected value 'Date After:2015-09-14T09:49:34'"));
+    }
+    
+    @Test
+    public void testDateAfterBefore_fail_beforeSameDate() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "date_after_before/dateAfterBefore_test_fail_beforeSameDate.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"startDateTime\":\"$LOCAL.DATETIME.BEFORE:2015-09-14T09:49:34.000Z\""));
+        
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "	\"status\": 200,\n" +
+                "	\"body\": {\n" +
+                " 		\"projectDetails\": {\n" +
+                "			\"startDateTime\": \"2015-09-14T09:49:34.000Z\",\n" +
+                "		}\n" +
+                "	}\n" +
+                "}";
+    
+        
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+        assertThat(failedReports.get(0).toString(),
+                is("Assertion path '$.body.projectDetails.startDateTime' with actual value '2015-09-14T09:49:34.000Z' "
+                		+ "did not match the expected value 'Date Before:2015-09-14T09:49:34'"));
+    }
+    
+    @Test
+    public void testValueOneOf_ValuePresent() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "one_of/oneOf_test_currentStatus.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"currentStatus\":\"$ONE.OF:[Found, Searching, Not Looking]\""));
+        	
+        	
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 200,\n" +
+                "    \"body\": {\n" +
+                "        \"currentStatus\": \"Searching\"\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+    
+    @Test
+    public void testValueOneOf_ValueNotPresent() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "one_of/oneOf_test_currentStatus.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"currentStatus\":\"$ONE.OF:[Found, Searching, Not Looking]\""));
+        	
+        	
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 200,\n" +
+                "    \"body\": {\n" +
+                "        \"currentStatus\": \"Quit\"\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+    }
+    
+    @Test
+    public void testValueOneOf_ActualResultNull() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "one_of/oneOf_test_currentStatus.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"currentStatus\":\"$ONE.OF:[Found, Searching, Not Looking]\""));
+        	
+        	
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 200,\n" +
+                "    \"body\": {\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+    }
+    
+    @Test
+    public void testValueOneOf_MatchEmptyString() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "one_of/oneOf_test_emptyString.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"currentStatus\":\"$ONE.OF:[Found, Searching,, Not Looking]\""));
+        	
+        	
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 200,\n" +
+                "    \"body\": {\n" +
+                "        \"currentStatus\": \"\"\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+    
+    @Test
+    public void testValueOneOf_MatchWhiteSpace() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "one_of/oneOf_test_whiteSpace.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"currentStatus\":\"$ONE.OF:[Found, Searching, , Not Looking]\""));
+        	
+        	
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 200,\n" +
+                "    \"body\": {\n" +
+                "        \"currentStatus\": \" \"\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(0));
+    }
+    
+    @Test
+    public void testValueOneOf_ExpectedArrayEmpty() throws Exception {
+        ScenarioSpec scenarioSpec = smartUtils.jsonFileToJava(
+                "one_of/oneOf_test_expectedArrayEmpty.json",
+                ScenarioSpec.class);
+
+        final String assertionsSectionAsString = scenarioSpec.getSteps().get(0).getAssertions().toString();
+        String mockScenarioState = "{}";
+
+        final String resolvedAssertions = jsonPreProcessor.resolveStringJson(assertionsSectionAsString, mockScenarioState);
+        assertThat(resolvedAssertions, containsString("\"currentStatus\":\"$ONE.OF:[]\""));
+        	
+        	
+        List<JsonAsserter> asserters = jsonPreProcessor.createAssertersFrom(resolvedAssertions);
+        assertThat(asserters.size(), is(2));
+
+        String mockTestResponse = "{\n" +
+                "    \"status\": 200,\n" +
+                "    \"body\": {\n" +
+                "        \"currentStatus\": \"Searching\"\n" +
+                "    }\n" +
+                "}";
+        List<AssertionReport> failedReports = jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse);
+
+        assertThat(failedReports.size(), is(1));
+    }
 }
\ No newline at end of file
diff --git a/core/src/test/resources/one_of/oneOf_test_currentStatus.json b/core/src/test/resources/one_of/oneOf_test_currentStatus.json
new file mode 100644
index 00000000..1297c701
--- /dev/null
+++ b/core/src/test/resources/one_of/oneOf_test_currentStatus.json
@@ -0,0 +1,18 @@
+{
+    "scenarioName": "Assert that 'currentStatus' is one of array items",
+    "steps": [
+        {
+            "name": "get_person_job_details",
+            "url": "",
+            "operation": "",
+            "request": {
+            },
+            "assertions": {
+                "status": 200,
+                "body": {
+                	"currentStatus": "$ONE.OF:[Found, Searching, Not Looking]"
+                }
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/core/src/test/resources/one_of/oneOf_test_emptyString.json b/core/src/test/resources/one_of/oneOf_test_emptyString.json
new file mode 100644
index 00000000..c1dae050
--- /dev/null
+++ b/core/src/test/resources/one_of/oneOf_test_emptyString.json
@@ -0,0 +1,18 @@
+{
+    "scenarioName": "Assert that 'currentStatus' is one of array items, including an empty string",
+    "steps": [
+        {
+            "name": "get_person_job_details",
+            "url": "",
+            "operation": "",
+            "request": {
+            },
+            "assertions": {
+                "status": 200,
+                "body": {
+                	"currentStatus": "$ONE.OF:[Found, Searching,, Not Looking]"
+                }
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/core/src/test/resources/one_of/oneOf_test_expectedArrayEmpty.json b/core/src/test/resources/one_of/oneOf_test_expectedArrayEmpty.json
new file mode 100644
index 00000000..663ffbd8
--- /dev/null
+++ b/core/src/test/resources/one_of/oneOf_test_expectedArrayEmpty.json
@@ -0,0 +1,18 @@
+{
+    "scenarioName": "Assert that 'currentStatus' is one of array items which is empty",
+    "steps": [
+        {
+            "name": "get_person_job_details",
+            "url": "",
+            "operation": "",
+            "request": {
+            },
+            "assertions": {
+                "status": 200,
+                "body": {
+                	"currentStatus": "$ONE.OF:[]"
+                }
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/core/src/test/resources/one_of/oneOf_test_whiteSpace.json b/core/src/test/resources/one_of/oneOf_test_whiteSpace.json
new file mode 100644
index 00000000..e3ae05cf
--- /dev/null
+++ b/core/src/test/resources/one_of/oneOf_test_whiteSpace.json
@@ -0,0 +1,18 @@
+{
+    "scenarioName": "Assert that 'currentStatus' is one of array items, including a whitespace",
+    "steps": [
+        {
+            "name": "get_person_job_details",
+            "url": "",
+            "operation": "",
+            "request": {
+            },
+            "assertions": {
+                "status": 200,
+                "body": {
+                	"currentStatus": "$ONE.OF:[Found, Searching, , Not Looking]"
+                }
+            }
+        }
+    ]
+}
\ No newline at end of file