From 015723787cbface7838090c792d742047a4a40c5 Mon Sep 17 00:00:00 2001 From: Patrik Helsing Date: Tue, 8 Dec 2015 23:29:34 +0100 Subject: [PATCH 1/4] [#119] First implementation of hamcrest-matchers --- .../com/jayway/jsonpath/matchers/IsJson.java | 69 ++++++++++ .../jayway/jsonpath/matchers/IsJsonFile.java | 17 +++ .../jsonpath/matchers/IsJsonString.java | 15 ++ .../jsonpath/matchers/JsonPathMatchers.java | 30 ++++ .../jsonpath/matchers/WithJsonPath.java | 75 ++++++++++ .../jayway/jsonpath/matchers/DemoTest.java | 66 +++++++++ .../jsonpath/matchers/IsJsonFileTest.java | 75 ++++++++++ .../jsonpath/matchers/IsJsonStringTest.java | 71 ++++++++++ .../jayway/jsonpath/matchers/IsJsonTest.java | 97 +++++++++++++ .../matchers/JsonPathMatchersTest.java | 130 ++++++++++++++++++ .../jsonpath/matchers/WithJsonPathTest.java | 122 ++++++++++++++++ .../matchers/helpers/ResourceHelpers.java | 35 +++++ .../helpers/StrictParsingConfiguration.java | 30 ++++ .../matchers/helpers/TestingMatchers.java | 33 +++++ .../src/test/resources/books.json | 38 +++++ .../src/test/resources/example.json | 4 + .../src/test/resources/invalid.json | 1 + 17 files changed, 908 insertions(+) create mode 100644 json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJson.java create mode 100644 json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonFile.java create mode 100644 json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonString.java create mode 100644 json-path-assert/src/main/java/com/jayway/jsonpath/matchers/JsonPathMatchers.java create mode 100644 json-path-assert/src/main/java/com/jayway/jsonpath/matchers/WithJsonPath.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/DemoTest.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonFileTest.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonStringTest.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonTest.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/JsonPathMatchersTest.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/WithJsonPathTest.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/ResourceHelpers.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/StrictParsingConfiguration.java create mode 100644 json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/TestingMatchers.java create mode 100644 json-path-assert/src/test/resources/books.json create mode 100644 json-path-assert/src/test/resources/example.json create mode 100644 json-path-assert/src/test/resources/invalid.json diff --git a/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJson.java b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJson.java new file mode 100644 index 00000000..9ee6681f --- /dev/null +++ b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJson.java @@ -0,0 +1,69 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.JsonPathException; +import com.jayway.jsonpath.ReadContext; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.io.File; +import java.io.IOException; + +public class IsJson extends TypeSafeMatcher { + private final Matcher jsonMatcher; + + protected IsJson(Matcher jsonMatcher) { + this.jsonMatcher = jsonMatcher; + } + + public static Matcher isJson(final Matcher matcher) { + return new IsJson(matcher); + } + + @Override + protected boolean matchesSafely(T json) { + try { + ReadContext context = parse(json); + return jsonMatcher.matches(context); + } catch (JsonPathException e) { + return false; + } catch (IOException e) { + return false; + } + } + + public void describeTo(Description description) { + description.appendText("is json ").appendDescriptionOf(jsonMatcher); + } + + @Override + protected void describeMismatchSafely(T json, Description mismatchDescription) { + try { + ReadContext context = parse(json); + jsonMatcher.describeMismatch(context, mismatchDescription); + } catch (JsonPathException e) { + buildMismatchDescription(json, mismatchDescription, e); + } catch (IOException e) { + buildMismatchDescription(json, mismatchDescription, e); + } + } + + private static void buildMismatchDescription(Object json, Description mismatchDescription, Exception e) { + mismatchDescription + .appendText("was ") + .appendValue(json) + .appendText(" which failed with ") + .appendValue(e.getMessage()); + } + + private static ReadContext parse(Object object) throws IOException { + if (object instanceof String) { + return JsonPath.parse((String) object); + } else if (object instanceof File) { + return JsonPath.parse((File) object); + } else { + return JsonPath.parse(object); + } + } +} diff --git a/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonFile.java b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonFile.java new file mode 100644 index 00000000..28d87977 --- /dev/null +++ b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonFile.java @@ -0,0 +1,17 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.ReadContext; +import org.hamcrest.Matcher; + +import java.io.File; + +public class IsJsonFile extends IsJson { + + IsJsonFile(Matcher jsonMatcher) { + super(jsonMatcher); + } + + public static Matcher isJsonFile(final Matcher matcher) { + return new IsJsonFile(matcher); + } +} diff --git a/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonString.java b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonString.java new file mode 100644 index 00000000..94e5225b --- /dev/null +++ b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJsonString.java @@ -0,0 +1,15 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.ReadContext; +import org.hamcrest.Matcher; + +public class IsJsonString extends IsJson { + + IsJsonString(Matcher jsonMatcher) { + super(jsonMatcher); + } + + public static Matcher isJsonString(final Matcher matcher) { + return new IsJsonString(matcher); + } +} diff --git a/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/JsonPathMatchers.java b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/JsonPathMatchers.java new file mode 100644 index 00000000..0c2e85fd --- /dev/null +++ b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/JsonPathMatchers.java @@ -0,0 +1,30 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.ReadContext; +import org.hamcrest.Matcher; + +import static com.jayway.jsonpath.matchers.WithJsonPath.withJsonPath; +import static org.hamcrest.Matchers.*; + +public class JsonPathMatchers { + + private JsonPathMatchers() { + throw new AssertionError("prevent instantiation"); + } + + public static Matcher hasJsonPath(String jsonPath) { + return hasJsonPath(jsonPath, not(anyOf(nullValue(), empty()))); + } + + public static Matcher hasJsonPath(final String jsonPath, final Matcher resultMatcher) { + return IsJson.isJson(withJsonPath(jsonPath, resultMatcher)); + } + + public static Matcher isJson() { + return IsJson.isJson(withJsonPath("$..*")); + } + + public static Matcher isJson(final Matcher matcher) { + return IsJson.isJson(matcher); + } +} diff --git a/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/WithJsonPath.java b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/WithJsonPath.java new file mode 100644 index 00000000..5c448898 --- /dev/null +++ b/json-path-assert/src/main/java/com/jayway/jsonpath/matchers/WithJsonPath.java @@ -0,0 +1,75 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.*; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import static org.hamcrest.Matchers.*; + +public class WithJsonPath extends TypeSafeMatcher { + private final JsonPath jsonPath; + private final Matcher resultMatcher; + + private WithJsonPath(JsonPath jsonPath, Matcher resultMatcher) { + this.jsonPath = jsonPath; + this.resultMatcher = resultMatcher; + } + + public static Matcher withJsonPath(String jsonPath, Predicate... filters) { + return withJsonPath(JsonPath.compile(jsonPath, filters)); + } + + public static Matcher withJsonPath(JsonPath jsonPath) { + return withJsonPath(jsonPath, not(anyOf(nullValue(), empty()))); + } + + public static Matcher withJsonPath(String jsonPath, Matcher resultMatcher) { + return withJsonPath(JsonPath.compile(jsonPath), resultMatcher); + } + + public static Matcher withJsonPath(final JsonPath jsonPath, final Matcher resultMatcher) { + return new WithJsonPath(jsonPath, resultMatcher); + } + + @Override + protected boolean matchesSafely(ReadContext context) { + try { + T value = context.read(jsonPath); + return resultMatcher.matches(value); + } catch (JsonPathException e) { + return false; + } + } + + public void describeTo(Description description) { + description + .appendText("with json path ") + .appendValue(jsonPath.getPath()) + .appendText(" evaluated to ") + .appendDescriptionOf(resultMatcher); + } + + @Override + protected void describeMismatchSafely(ReadContext context, Description mismatchDescription) { + try { + T value = jsonPath.read(context.json()); + mismatchDescription + .appendText("json path ") + .appendValue(jsonPath.getPath()) + .appendText(" was evaluated to ") + .appendValue(value); + } catch (PathNotFoundException e) { + mismatchDescription + .appendText("json path ") + .appendValue(jsonPath.getPath()) + .appendText(" was not found in ") + .appendValue(context.json()); + } catch (JsonPathException e) { + mismatchDescription + .appendText("was ") + .appendValue(context.json()); + } + } + +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/DemoTest.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/DemoTest.java new file mode 100644 index 00000000..f6d0a15c --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/DemoTest.java @@ -0,0 +1,66 @@ +package com.jayway.jsonpath.matchers; + +import org.junit.Ignore; +import org.junit.Test; + +import java.io.File; + +import static com.jayway.jsonpath.matchers.IsJsonFile.isJsonFile; +import static com.jayway.jsonpath.matchers.IsJsonString.isJsonString; +import static com.jayway.jsonpath.matchers.JsonPathMatchers.isJson; +import static com.jayway.jsonpath.matchers.WithJsonPath.withJsonPath; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +@Ignore +public class DemoTest { + @Test + public void shouldFailOnJsonString() { + String json = resource("books.json"); + assertThat(json, isJson(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnJsonFile() { + File json = resourceAsFile("books.json"); + assertThat(json, isJson(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnInvalidJsonString() { + String json = resource("invalid.json"); + assertThat(json, isJson(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnInvalidJsonFile() { + File json = resourceAsFile("invalid.json"); + assertThat(json, isJson(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnTypedJsonString() { + String json = resource("books.json"); + assertThat(json, isJsonString(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnTypedJsonFile() { + File json = resourceAsFile("books.json"); + assertThat(json, isJsonFile(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnTypedInvalidJsonString() { + String json = resource("invalid.json"); + assertThat(json, isJsonString(withJsonPath("$.store.name", equalTo("The Shop")))); + } + + @Test + public void shouldFailOnTypedInvalidJsonFile() { + File json = resourceAsFile("invalid.json"); + assertThat(json, isJsonFile(withJsonPath("$.store.name", equalTo("The Shop")))); + } +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonFileTest.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonFileTest.java new file mode 100644 index 00000000..3acb484f --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonFileTest.java @@ -0,0 +1,75 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +import static com.jayway.jsonpath.matchers.IsJsonFile.isJsonFile; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile; +import static com.jayway.jsonpath.matchers.helpers.TestingMatchers.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class IsJsonFileTest { + private static final File BOOKS_JSON = resourceAsFile("books.json"); + private static final File INVALID_JSON = resourceAsFile("invalid.json"); + + @BeforeClass + public static void setupStrictJsonParsing() { + Configuration.setDefaults(new StrictParsingConfiguration()); + } + + @AfterClass + public static void setupDefaultJsonParsing() { + Configuration.setDefaults(null); + } + + @Test + public void shouldMatchJsonFileEvaluatedToTrue() { + assertThat(BOOKS_JSON, isJsonFile(withPathEvaluatedTo(true))); + } + + @Test + public void shouldNotMatchJsonFileEvaluatedToFalse() { + assertThat(BOOKS_JSON, not(isJsonFile(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldNotMatchInvalidJsonFile() { + assertThat(INVALID_JSON, not(isJsonFile(withPathEvaluatedTo(true)))); + assertThat(INVALID_JSON, not(isJsonFile(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldBeDescriptive() { + Matcher matcher = isJsonFile(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeTo(description); + assertThat(description.toString(), startsWith("is json")); + assertThat(description.toString(), containsString(MATCH_TRUE_TEXT)); + } + + @Test + public void shouldDescribeMismatchOfValidJson() { + Matcher matcher = isJsonFile(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeMismatch(BOOKS_JSON, description); + assertThat(description.toString(), containsString(MISMATCHED_TEXT)); + } + + @Test + public void shouldDescribeMismatchOfInvalidJson() { + Matcher matcher = isJsonFile(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeMismatch(INVALID_JSON, description); + assertThat(description.toString(), containsString("invalid.json")); + assertThat(description.toString(), containsString("invalid-json")); + } +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonStringTest.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonStringTest.java new file mode 100644 index 00000000..4935c16f --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonStringTest.java @@ -0,0 +1,71 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import static com.jayway.jsonpath.matchers.IsJsonString.isJsonString; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource; +import static com.jayway.jsonpath.matchers.helpers.TestingMatchers.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class IsJsonStringTest { + private static final String BOOKS_JSON = resource("books.json"); + + @BeforeClass + public static void setupStrictJsonParsing() { + Configuration.setDefaults(new StrictParsingConfiguration()); + } + + @AfterClass + public static void setupDefaultJsonParsing() { + Configuration.setDefaults(null); + } + + @Test + public void shouldMatchJsonStringEvaluatedToTrue() { + assertThat(BOOKS_JSON, isJsonString(withPathEvaluatedTo(true))); + } + + @Test + public void shouldNotMatchJsonStringEvaluatedToFalse() { + assertThat(BOOKS_JSON, not(isJsonString(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldNotMatchInvalidJsonString() { + assertThat("invalid-json", not(isJsonString(withPathEvaluatedTo(true)))); + assertThat("invalid-json", not(isJsonString(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldBeDescriptive() { + Matcher matcher = isJsonString(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeTo(description); + assertThat(description.toString(), startsWith("is json")); + assertThat(description.toString(), containsString(MATCH_TRUE_TEXT)); + } + + @Test + public void shouldDescribeMismatchOfValidJson() { + Matcher matcher = isJsonString(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeMismatch(BOOKS_JSON, description); + assertThat(description.toString(), containsString(MISMATCHED_TEXT)); + } + + @Test + public void shouldDescribeMismatchOfInvalidJson() { + Matcher matcher = isJsonString(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeMismatch("invalid-json", description); + assertThat(description.toString(), containsString("\"invalid-json\"")); + } +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonTest.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonTest.java new file mode 100644 index 00000000..4d29a43a --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonTest.java @@ -0,0 +1,97 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration; +import com.jayway.jsonpath.matchers.helpers.TestingMatchers; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +import static com.jayway.jsonpath.matchers.IsJson.isJson; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile; +import static com.jayway.jsonpath.matchers.helpers.TestingMatchers.withPathEvaluatedTo; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class IsJsonTest { + private static final String BOOKS_JSON_STRING = resource("books.json"); + private static final File BOOKS_JSON_FILE = resourceAsFile("books.json"); + + @BeforeClass + public static void setupStrictJsonParsing() { + Configuration.setDefaults(new StrictParsingConfiguration()); + } + + @AfterClass + public static void setupDefaultJsonParsing() { + Configuration.setDefaults(null); + } + + @Test + public void shouldMatchJsonObjectEvaluatedToTrue() { + Object parsedJson = parseJson(BOOKS_JSON_STRING); + assertThat(parsedJson, isJson(withPathEvaluatedTo(true))); + } + + @Test + public void shouldNotMatchJsonObjectEvaluatedToFalse() { + Object parsedJson = parseJson(BOOKS_JSON_STRING); + assertThat(parsedJson, not(isJson(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldMatchJsonStringEvaluatedToTrue() { + assertThat(BOOKS_JSON_STRING, isJson(withPathEvaluatedTo(true))); + } + + @Test + public void shouldNotMatchJsonStringEvaluatedToFalse() { + assertThat(BOOKS_JSON_STRING, not(isJson(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldMatchJsonFileEvaluatedToTrue() { + assertThat(BOOKS_JSON_FILE, isJson(withPathEvaluatedTo(true))); + } + + @Test + public void shouldNotMatchJsonFileEvaluatedToFalse() { + assertThat(BOOKS_JSON_FILE, not(isJson(withPathEvaluatedTo(false)))); + } + + @Test + public void shouldBeDescriptive() { + Matcher matcher = isJson(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeTo(description); + assertThat(description.toString(), startsWith("is json")); + assertThat(description.toString(), containsString(TestingMatchers.MATCH_TRUE_TEXT)); + } + + @Test + public void shouldDescribeMismatchOfValidJson() { + Matcher matcher = isJson(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeMismatch(BOOKS_JSON_STRING, description); + assertThat(description.toString(), containsString(TestingMatchers.MISMATCHED_TEXT)); + } + + @Test + public void shouldDescribeMismatchOfInvalidJson() { + Matcher matcher = isJson(withPathEvaluatedTo(true)); + Description description = new StringDescription(); + matcher.describeMismatch("invalid-json", description); + assertThat(description.toString(), containsString("\"invalid-json\"")); + } + + private static Object parseJson(String json) { + return Configuration.defaultConfiguration().jsonProvider().parse(json); + } + +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/JsonPathMatchersTest.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/JsonPathMatchersTest.java new file mode 100644 index 00000000..4967bce6 --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/JsonPathMatchersTest.java @@ -0,0 +1,130 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.nio.file.Paths; +import java.util.Collection; + +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static com.jayway.jsonpath.matchers.JsonPathMatchers.isJson; +import static com.jayway.jsonpath.matchers.WithJsonPath.withJsonPath; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class JsonPathMatchersTest { + + private static final String VALID_JSON = resource("example.json"); + private static final String BOOKS_JSON = resource("books.json"); + private static final String INVALID_JSON = "{ invalid-json }"; + private static final File BOOKS_JSON_FILE = resourceAsFile("books.json"); + + @BeforeClass + public static void setupStrictJsonParsing() { + // NOTE: Evaluation depends on the default configuration of JsonPath + Configuration.setDefaults(new StrictParsingConfiguration()); + } + + @AfterClass + public static void setupDefaultJsonParsing() { + Configuration.setDefaults(null); + } + + @Test + public void shouldMatchValidJson() { + assertThat(VALID_JSON, isJson()); + assertThat(BOOKS_JSON, isJson()); + } + + @Test + public void shouldNotMatchInvalidJson() { + assertThat(INVALID_JSON, not(isJson())); + assertThat(new Object(), not(isJson())); + assertThat("{}", not(isJson())); + assertThat(null, not(isJson())); + } + + @Test + public void shouldMatchExistingJsonPath() { + assertThat(BOOKS_JSON, hasJsonPath("$.store.name")); + assertThat(BOOKS_JSON, hasJsonPath("$.store.book[2].title")); + assertThat(BOOKS_JSON, hasJsonPath("$.store.book[*].author")); + } + + @Test + public void shouldMatchExistingJsonPathAlternative() { + assertThat(BOOKS_JSON, isJson(withJsonPath("$.store.name"))); + assertThat(BOOKS_JSON, isJson(withJsonPath("$.store.book[2].title"))); + assertThat(BOOKS_JSON, isJson(withJsonPath("$.store.book[*].author"))); + } + + @Test + public void shouldNotMatchInvalidJsonWithPath() { + assertThat(INVALID_JSON, not(hasJsonPath("$.path"))); + assertThat(new Object(), not(hasJsonPath("$.path"))); + assertThat("{}", not(hasJsonPath("$.path"))); + assertThat(null, not(hasJsonPath("$.path"))); + } + + @Test + public void shouldNotMatchInvalidJsonWithPathAndValue() { + assertThat(INVALID_JSON, not(hasJsonPath("$.path", anything()))); + assertThat(new Object(), not(hasJsonPath("$.path", anything()))); + assertThat(null, not(hasJsonPath("$.message", anything()))); + } + + @Test + public void shouldNotMatchNonExistingJsonPath() { + assertThat(BOOKS_JSON, not(hasJsonPath("$.not_there"))); + assertThat(BOOKS_JSON, not(hasJsonPath("$.store.book[5].title"))); + assertThat(BOOKS_JSON, not(hasJsonPath("$.store.book[*].not_there"))); + } + + @Test + public void shouldNotMatchNonExistingJsonPathAlternative() { + assertThat(BOOKS_JSON, not(isJson(withJsonPath("$.not_there")))); + assertThat(BOOKS_JSON, not(isJson(withJsonPath("$.store.book[5].title")))); + assertThat(BOOKS_JSON, not(isJson(withJsonPath("$.store.book[*].not_there")))); + } + + @Test + public void shouldMatchJsonPathWithStringValue() { + assertThat(BOOKS_JSON, hasJsonPath("$.store.name", equalTo("Little Shop"))); + assertThat(BOOKS_JSON, hasJsonPath("$.store.book[2].title", equalTo("Moby Dick"))); + } + + @Test + public void shouldMatchJsonPathWithIntegerValue() { + assertThat(BOOKS_JSON, hasJsonPath("$.expensive", equalTo(10))); + } + + @Test + public void shouldMatchJsonPathWithDoubleValue() { + assertThat(BOOKS_JSON, hasJsonPath("$.store.bicycle.price", equalTo(19.95))); + } + + @Test + public void shouldMatchJsonPathWithCollectionValue() { + assertThat(BOOKS_JSON, hasJsonPath("$.store.book[*].author", instanceOf(Collection.class))); + assertThat(BOOKS_JSON, hasJsonPath("$.store.book[*].author", hasSize(4))); + assertThat(BOOKS_JSON, hasJsonPath("$.store.book[*].author", hasItem("Evelyn Waugh"))); + assertThat(BOOKS_JSON, hasJsonPath("$..book[2].title", hasItem("Moby Dick"))); + } + + @Test + public void shouldMatchJsonPathOnFile() { + assertThat(BOOKS_JSON_FILE, hasJsonPath("$.store.name", equalTo("Little Shop"))); + } + + @Test + public void shouldNotMatchJsonPathOnNonExistingFile() { + File nonExistingFile = Paths.get("missing-file").toFile(); + assertThat(nonExistingFile, not(hasJsonPath("$..*", anything()))); + } +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/WithJsonPathTest.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/WithJsonPathTest.java new file mode 100644 index 00000000..de4a45fa --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/WithJsonPathTest.java @@ -0,0 +1,122 @@ +package com.jayway.jsonpath.matchers; + +import com.jayway.jsonpath.InvalidPathException; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.ReadContext; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; +import org.junit.Test; + +import java.util.Collection; + +import static com.jayway.jsonpath.JsonPath.compile; +import static com.jayway.jsonpath.matchers.WithJsonPath.withJsonPath; +import static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class WithJsonPathTest { + private static final ReadContext BOOKS_JSON = JsonPath.parse(resource("books.json")); + + @Test + public void shouldMatchExistingCompiledJsonPath() { + assertThat(BOOKS_JSON, withJsonPath(compile("$.expensive"))); + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.bicycle"))); + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.book[2].title"))); + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.book[*].author"))); + } + + @Test + public void shouldMatchExistingStringJsonPath() { + assertThat(BOOKS_JSON, withJsonPath("$.expensive")); + assertThat(BOOKS_JSON, withJsonPath("$.store.bicycle")); + assertThat(BOOKS_JSON, withJsonPath("$.store.book[2].title")); + assertThat(BOOKS_JSON, withJsonPath("$.store.book[*].author")); + } + + @Test + public void shouldNotMatchNonExistingJsonPath() { + assertThat(BOOKS_JSON, not(withJsonPath(compile("$.not_there")))); + assertThat(BOOKS_JSON, not(withJsonPath(compile("$.store.book[5].title")))); + assertThat(BOOKS_JSON, not(withJsonPath(compile("$.store.book[*].not_there")))); + } + + @Test + public void shouldNotMatchNonExistingStringJsonPath() { + assertThat(BOOKS_JSON, not(withJsonPath("$.not_there"))); + assertThat(BOOKS_JSON, not(withJsonPath("$.store.book[5].title"))); + assertThat(BOOKS_JSON, not(withJsonPath("$.store.book[*].not_there"))); + } + + @Test + public void shouldMatchJsonPathEvaluatedToStringValue() { + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.bicycle.color"), equalTo("red"))); + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.book[2].title"), equalTo("Moby Dick"))); + assertThat(BOOKS_JSON, withJsonPath("$.store.name", equalTo("Little Shop"))); + assertThat(BOOKS_JSON, withJsonPath("$.store.book[2].title", equalTo("Moby Dick"))); + } + + @Test + public void shouldMatchJsonPathEvaluatedToIntegerValue() { + assertThat(BOOKS_JSON, withJsonPath(compile("$.expensive"), equalTo(10))); + assertThat(BOOKS_JSON, withJsonPath("$.expensive", equalTo(10))); + } + + @Test + public void shouldMatchJsonPathEvaluatedToDoubleValue() { + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.bicycle.price"), equalTo(19.95))); + assertThat(BOOKS_JSON, withJsonPath("$.store.bicycle.price", equalTo(19.95))); + } + + @Test + public void shouldMatchJsonPathEvaluatedToCollectionValue() { + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.book[*].author"), instanceOf(Collection.class))); + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.book[*].author"), hasSize(4))); + assertThat(BOOKS_JSON, withJsonPath(compile("$.store.book[*].author"), hasItem("Evelyn Waugh"))); + assertThat(BOOKS_JSON, withJsonPath(compile("$..book[2].title"), hasItem("Moby Dick"))); + assertThat(BOOKS_JSON, withJsonPath("$.store.book[*].author", instanceOf(Collection.class))); + assertThat(BOOKS_JSON, withJsonPath("$.store.book[*].author", hasSize(4))); + assertThat(BOOKS_JSON, withJsonPath("$.store.book[*].author", hasItem("Evelyn Waugh"))); + assertThat(BOOKS_JSON, withJsonPath("$..book[2].title", hasItem("Moby Dick"))); + } + + @Test(expected = InvalidPathException.class) + public void shouldFailOnInvalidJsonPath() { + withJsonPath("$[}"); + } + + @Test + public void shouldNotMatchOnInvalidJson() { + ReadContext invalidJson = JsonPath.parse("invalid-json"); + assertThat(invalidJson, not(withJsonPath("$.expensive", equalTo(10)))); + } + + @Test + public void shouldBeDescriptive() { + Matcher matcher = withJsonPath("path", equalTo(2)); + Description description = new StringDescription(); + matcher.describeTo(description); + assertThat(description.toString(), containsString("path")); + assertThat(description.toString(), containsString("<2>")); + } + + @Test + public void shouldDescribeMismatchOfEvaluation() { + Matcher matcher = withJsonPath("expensive", equalTo(3)); + Description description = new StringDescription(); + matcher.describeMismatch(BOOKS_JSON, description); + assertThat(description.toString(), containsString("expensive")); + assertThat(description.toString(), containsString("<10>")); + } + + @Test + public void shouldDescribeMismatchOfPathNotFound() { + Matcher matcher = withJsonPath("not-here", equalTo(3)); + Description description = new StringDescription(); + matcher.describeMismatch(BOOKS_JSON, description); + assertThat(description.toString(), containsString("not-here")); + assertThat(description.toString(), containsString("was not found")); + } + +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/ResourceHelpers.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/ResourceHelpers.java new file mode 100644 index 00000000..c2c8724a --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/ResourceHelpers.java @@ -0,0 +1,35 @@ +package com.jayway.jsonpath.matchers.helpers; + +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static java.lang.ClassLoader.getSystemResource; +import static java.lang.ClassLoader.getSystemResourceAsStream; + +public class ResourceHelpers { + public static String resource(String resource) { + try { + return IOUtils.toString(getSystemResourceAsStream(resource)); + } catch (IOException e) { + throw new AssertionError("Resource not found", e); + } + } + + public static File resourceAsFile(String resource) { + try { + URL systemResource = getSystemResource(resource); + URI uri = systemResource.toURI(); + Path path = Paths.get(uri); + return path.toFile(); + } catch (URISyntaxException e) { + throw new AssertionError("URI syntax error", e); + } + } +} diff --git a/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/StrictParsingConfiguration.java b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/StrictParsingConfiguration.java new file mode 100644 index 00000000..bfec47b2 --- /dev/null +++ b/json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/StrictParsingConfiguration.java @@ -0,0 +1,30 @@ +package com.jayway.jsonpath.matchers.helpers; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.Option; +import com.jayway.jsonpath.spi.json.JsonProvider; +import com.jayway.jsonpath.spi.json.JsonSmartJsonProvider; +import com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider; +import com.jayway.jsonpath.spi.mapper.MappingProvider; +import net.minidev.json.parser.JSONParser; + +import java.util.EnumSet; +import java.util.Set; + +public class StrictParsingConfiguration implements Configuration.Defaults { + + private final JsonProvider jsonProvider = new JsonSmartJsonProvider(JSONParser.MODE_STRICTEST); + private final MappingProvider mappingProvider = new JsonSmartMappingProvider(); + + public JsonProvider jsonProvider() { + return jsonProvider; + } + + public MappingProvider mappingProvider() { + return mappingProvider; + } + + public Set