diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java
new file mode 100644
index 0000000000..43e2d673fb
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+
+import org.assertj.core.api.Assertions;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.core.ResolvableType;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+import org.springframework.util.Assert;
+import org.springframework.util.ReflectionUtils;
+import org.springframework.util.ReflectionUtils.FieldCallback;
+
+/**
+ * Base class for AssertJ based JSON marshal testers. Exposes specific Asserts following a
+ * {@code read}, {@code write} or {@code parse} of JSON content. Typically used in
+ * combination with an AssertJ {@link Assertions#assertThat(Object) assertThat} call. For
+ * example:
+ * public class ExampleObjectJsonTests {
+ *
+ * private AbstractJsonTester<ExampleObject> json = //...
+ *
+ * @Test
+ * public void testWriteJson() {
+ * ExampleObject object = //...
+ * assertThat(json.write(object)).isEqualToJson("expected.json");
+ * assertThat(json.read("expected.json)).isEqualTo(object);
+ * }
+ *
+ * }
+ * For a complete list of supported assertions see {@link JsonContentAssert} and
+ * {@link ObjectContentAssert}.
+ *
+ * To use this library JSONAssert must be on the test classpath.
+ *
+ * @param The type under test
+ * @author Phillip Webb
+ * @since 1.4.0
+ * @see JsonContentAssert
+ * @see ObjectContentAssert
+ */
+public abstract class AbstractJsonMarshalTester {
+
+ private final Class> resourceLoadClass;
+
+ private final ResolvableType type;
+
+ /**
+ * Create a new {@link AbstractJsonMarshalTester} instance.
+ * @param resourceLoadClass the source class used when loading relative classpath
+ * resources
+ * @param type the type under test
+ */
+ public AbstractJsonMarshalTester(Class> resourceLoadClass, ResolvableType type) {
+ Assert.notNull(resourceLoadClass, "ResourceLoadClass must not be null");
+ Assert.notNull(type, "Type must not be null");
+ this.resourceLoadClass = resourceLoadClass;
+ this.type = type;
+ }
+
+ /**
+ * Return the type under test.
+ * @return the type under test
+ */
+ protected final ResolvableType getType() {
+ return this.type;
+ }
+
+ /**
+ * Return {@link JsonContent} from writing the specific value.
+ * @param value the value to write
+ * @return the {@link JsonContent}
+ * @throws IOException on write error
+ */
+ public JsonContent write(T value) throws IOException {
+ Assert.notNull(value, "Value must not be null");
+ String json = writeObject(value, this.type);
+ return new JsonContent(this.resourceLoadClass, this.type, json);
+ }
+
+ /**
+ * Return the object created from parsing the specific JSON bytes.
+ * @param jsonBytes the source JSON bytes
+ * @return the resulting object
+ * @throws IOException on parse error
+ */
+ public T parseObject(byte[] jsonBytes) throws IOException {
+ return parse(jsonBytes).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from parsing the specific JSON bytes.
+ * @param jsonBytes the source JSON bytes
+ * @return the {@link ObjectContent}
+ * @throws IOException on parse error
+ */
+ public ObjectContent parse(byte[] jsonBytes) throws IOException {
+ Assert.notNull(jsonBytes, "JsonBytes must not be null");
+ return read(new ByteArrayResource(jsonBytes));
+ }
+
+ /**
+ * Return the object created from parsing the specific JSON String.
+ * @param jsonString the source JSON string
+ * @return the resulting object
+ * @throws IOException on parse error
+ */
+ public T parseObject(String jsonString) throws IOException {
+ return parse(jsonString).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from parsing the specific JSON String.
+ * @param jsonString the source JSON string
+ * @return the {@link ObjectContent}
+ * @throws IOException on parse error
+ */
+ public ObjectContent parse(String jsonString) throws IOException {
+ Assert.notNull(jsonString, "JsonString must not be null");
+ return read(new StringReader(jsonString));
+ }
+
+ /**
+ * Return the object created from reading from the specified classpath resource.
+ * @param resourcePath the source resource path. May be a full path or a path relative
+ * to the {@code resourceLoadClass} passed to the constructor
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ public T readObject(String resourcePath) throws IOException {
+ return read(resourcePath).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from reading from the specified classpath resource.
+ * @param resourcePath the source resource path. May be a full path or a path relative
+ * to the {@code resourceLoadClass} passed to the constructor
+ * @return the {@link ObjectContent}
+ * @throws IOException on read error
+ */
+ public ObjectContent read(String resourcePath) throws IOException {
+ Assert.notNull(resourcePath, "ResourcePath must not be null");
+ return read(new ClassPathResource(resourcePath, this.resourceLoadClass));
+ }
+
+ /**
+ * Return the object created from reading from the specified file.
+ * @param file the source file
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ public T readObject(File file) throws IOException {
+ return read(file).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from reading from the specified file.
+ * @param file the source file
+ * @return the {@link ObjectContent}
+ * @throws IOException on read error
+ */
+ public ObjectContent read(File file) throws IOException {
+ Assert.notNull(file, "File must not be null");
+ return read(new FileSystemResource(file));
+ }
+
+ /**
+ * Return the object created from reading from the specified input stream.
+ * @param inputStream the source input stream
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ public T readObject(InputStream inputStream) throws IOException {
+ return read(inputStream).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from reading from the specified input stream.
+ * @param inputStream the source input stream
+ * @return the {@link ObjectContent}
+ * @throws IOException on read error
+ */
+ public ObjectContent read(InputStream inputStream) throws IOException {
+ Assert.notNull(inputStream, "InputStream must not be null");
+ return read(new InputStreamResource(inputStream));
+ }
+
+ /**
+ * Return the object created from reading from the specified resource.
+ * @param resource the source resource
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ public T readObject(Resource resource) throws IOException {
+ return read(resource).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from reading from the specified resource.
+ * @param resource the source resource
+ * @return the {@link ObjectContent}
+ * @throws IOException on read error
+ */
+ public ObjectContent read(Resource resource) throws IOException {
+ Assert.notNull(resource, "Resource must not be null");
+ InputStream inputStream = resource.getInputStream();
+ T object = readObject(inputStream, this.type);
+ closeQuietly(inputStream);
+ return new ObjectContent(this.type, object);
+ }
+
+ /**
+ * Return the object created from reading from the specified reader.
+ * @param reader the source reader
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ public T readObject(Reader reader) throws IOException {
+ return read(reader).getObject();
+ }
+
+ /**
+ * Return {@link ObjectContent} from reading from the specified reader.
+ * @param reader the source reader
+ * @return the {@link ObjectContent}
+ * @throws IOException on read error
+ */
+ public ObjectContent read(Reader reader) throws IOException {
+ Assert.notNull(reader, "Reader must not be null");
+ T object = readObject(reader, this.type);
+ closeQuietly(reader);
+ return new ObjectContent(this.type, object);
+ }
+
+ private void closeQuietly(Closeable closeable) {
+ try {
+ closeable.close();
+ }
+ catch (IOException ex) {
+ }
+ }
+
+ /**
+ * Write the specified object to a JSON string.
+ * @param value the source value ({@code never null})
+ * @param type the resulting type ({@code never null})
+ * @return the JSON string
+ * @throws IOException on write error
+ */
+ protected abstract String writeObject(T value, ResolvableType type)
+ throws IOException;
+
+ /**
+ * Read from the specified input stream to create an object of the specified type. The
+ * default implementation delegates to {@link #readObject(Reader, ResolvableType)}
+ * @param inputStream the source input stream ({@code never null})
+ * @param type the resulting type ({@code never null})
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ protected T readObject(InputStream inputStream, ResolvableType type)
+ throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ return readObject(reader, type);
+ }
+
+ /**
+ * Read from the specified reader to create an object of the specified type.
+ * @param reader the source reader ({@code never null})
+ * @param type the resulting type ({@code never null})
+ * @return the resulting object
+ * @throws IOException on read error
+ */
+ protected abstract T readObject(Reader reader, ResolvableType type)
+ throws IOException;
+
+ /**
+ * Utility class used to support field initialization. Uses by subclasses to support
+ * {@code initFields}.
+ * @param The marshaller type
+ */
+ protected static abstract class FieldInitializer {
+
+ private final Class> testerClass;
+
+ @SuppressWarnings("rawtypes")
+ protected FieldInitializer(
+ Class extends AbstractJsonMarshalTester> testerClass) {
+ Assert.notNull(testerClass, "TesterClass must not be null");
+ this.testerClass = testerClass;
+ }
+
+ public void initFields(final Object testInstance, final M marshaller) {
+ Assert.notNull(testInstance, "TestInstance must not be null");
+ Assert.notNull(marshaller, "Marshaller must not be null");
+ initFields(testInstance, new ObjectFactory() {
+
+ @Override
+ public M getObject() throws BeansException {
+ return marshaller;
+ }
+
+ });
+ }
+
+ public void initFields(final Object testInstance,
+ final ObjectFactory marshaller) {
+ Assert.notNull(testInstance, "TestInstance must not be null");
+ Assert.notNull(marshaller, "Marshaller must not be null");
+ ReflectionUtils.doWithFields(testInstance.getClass(), new FieldCallback() {
+
+ @Override
+ public void doWith(Field field)
+ throws IllegalArgumentException, IllegalAccessException {
+ doWithField(field, testInstance, marshaller);
+ }
+
+ });
+ }
+
+ protected void doWithField(Field field, Object test,
+ ObjectFactory marshaller) {
+ if (this.testerClass.isAssignableFrom(field.getType())) {
+ ReflectionUtils.makeAccessible(field);
+ Object existingValue = ReflectionUtils.getField(field, test);
+ if (existingValue == null) {
+ setupField(field, test, marshaller);
+ }
+ }
+ }
+
+ private void setupField(Field field, Object test, ObjectFactory marshaller) {
+ ResolvableType type = ResolvableType.forField(field).getGeneric();
+ ReflectionUtils.setField(field, test,
+ createTester(test.getClass(), type, marshaller.getObject()));
+ }
+
+ protected abstract AbstractJsonMarshalTester createTester(
+ Class> resourceLoadClass, ResolvableType type, M marshaller);
+
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/BasicJsonTester.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/BasicJsonTester.java
new file mode 100644
index 0000000000..9ce37b8883
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/BasicJsonTester.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.springframework.core.io.Resource;
+import org.springframework.util.Assert;
+
+/**
+ * AssertJ based JSON tester that works with basic JSON strings. Allows testing of JSON
+ * payloads created from some any source, for example:
+ * public class ExampleObjectJsonTests {
+ *
+ * private BasicJsonTester = new BasicJsonTester(getClass());
+ *
+ * @Test
+ * public void testWriteJson() {
+ * assertThat(json.from("example.json")).extractingJsonPathStringValue("@.name")
+ .isEqualTo("Spring");
+ * }
+ *
+ * }
+ *
+ *
+ * See {@link AbstractJsonMarshalTester} for more details.
+ *
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public class BasicJsonTester {
+
+ private final JsonLoader loader;
+
+ /**
+ * Create a new {@link BasicJsonTester} instance.
+ * @param resourceLoadClass the source class used to load resources
+ */
+ public BasicJsonTester(Class> resourceLoadClass) {
+ Assert.notNull(resourceLoadClass, "ResourceLoadClass must not be null");
+ this.loader = new JsonLoader(resourceLoadClass);
+ }
+
+ /**
+ * Create JSON content from the specified String source. The source can contain the
+ * JSON itself or, if it ends with {@code .json}, the name of a resource to be loaded
+ * using {@code resourceLoadClass}.
+ * @param source JSON content or a {@code .json} resource name
+ * @return the JSON content
+ * @throws IOException on load error
+ */
+ public JsonContent from(CharSequence source) throws IOException {
+ return getJsonContent(this.loader.getJson(source));
+ }
+
+ /**
+ * Create JSON content from the specified resource path.
+ * @param path the path of the resource to load
+ * @param resourceLoadClass the classloader used load the resource
+ * @return the JSON content
+ * @throws IOException on load error
+ */
+ public JsonContent from(String path, Class> resourceLoadClass)
+ throws IOException {
+ return getJsonContent(this.loader.getJson(path, resourceLoadClass));
+ }
+
+ /**
+ * Create JSON content from the specified JSON bytes.
+ * @param source the bytes of JSON
+ * @return the JSON content
+ * @throws IOException on load error
+ */
+ public JsonContent from(byte[] source) throws IOException {
+ return getJsonContent(this.loader.getJson(source));
+ }
+
+ /**
+ * Create JSON content from the specified JSON file.
+ * @param source the file containing JSON
+ * @return the JSON content
+ * @throws IOException on load error
+ */
+ public JsonContent from(File source) throws IOException {
+ return getJsonContent(this.loader.getJson(source));
+ }
+
+ /**
+ * Create JSON content from the specified JSON input stream.
+ * @param source the input stream containing JSON
+ * @return the JSON content
+ * @throws IOException on load error
+ */
+ public JsonContent from(InputStream source) throws IOException {
+ return getJsonContent(this.loader.getJson(source));
+ }
+
+ /**
+ * Create JSON content from the specified JSON resource.
+ * @param source the resource containing JSON
+ * @return the JSON content
+ * @throws IOException on load error
+ */
+ public JsonContent from(Resource source) throws IOException {
+ return getJsonContent(this.loader.getJson(source));
+ }
+
+ private JsonContent getJsonContent(String json) {
+ return new JsonContent(this.loader.getResourceLoadClass(), null, json);
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java
new file mode 100644
index 0000000000..a27da3723e
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import com.google.gson.Gson;
+
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.core.ResolvableType;
+import org.springframework.util.Assert;
+
+/**
+ * AssertJ based JSON tester backed by Gson. Usually instantiated via
+ * {@link #initFields(Object, Gson)}, for example:
+ * public class ExampleObjectJsonTests {
+ *
+ * private GsonTester<ExampleObject> json;
+ *
+ * @Before
+ * public void setup() {
+ * Gson gson = new GsonBuilder().create();
+ * GsonTester.initFields(this, gson);
+ * }
+ *
+ * @Test
+ * public void testWriteJson() {
+ * ExampleObject object = //...
+ * assertThat(json.write(object)).isEqualToJson("expected.json");
+ * }
+ *
+ * }
+ *
+ *
+ * See {@link AbstractJsonMarshalTester} for more details.
+ *
+ * @param The type under test
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public class GsonTester extends AbstractJsonMarshalTester {
+
+ private final Gson gson;
+
+ /**
+ * Create a new {@link GsonTester} instance.
+ * @param resourceLoadClass the source class used to load resources
+ * @param type the type under test
+ * @param gson the Gson instance
+ * @see #initFields(Object, Gson)
+ */
+ public GsonTester(Class> resourceLoadClass, ResolvableType type, Gson gson) {
+ super(resourceLoadClass, type);
+ Assert.notNull(gson, "Gson must not be null");
+ this.gson = gson;
+ }
+
+ @Override
+ protected String writeObject(T value, ResolvableType type) throws IOException {
+ return this.gson.toJson(value, type.getType());
+ }
+
+ @Override
+ protected T readObject(Reader reader, ResolvableType type) throws IOException {
+ return this.gson.fromJson(reader, type.getType());
+ }
+
+ /**
+ * Utility method to initialize {@link JacksonTester} fields. See {@link JacksonTester
+ * class-level documentation} for example usage.
+ * @param testInstance the test instance
+ * @param gson the Gson instance
+ */
+ public static void initFields(Object testInstance, Gson gson) {
+ new GsonFieldInitializer().initFields(testInstance, gson);
+ }
+
+ /**
+ * Utility method to initialize {@link JacksonTester} fields. See {@link JacksonTester
+ * class-level documentation} for example usage.
+ * @param testInstance the test instance
+ * @param gson an object factory to create the Gson instance
+ */
+ public static void initFields(Object testInstance, ObjectFactory gson) {
+ new GsonFieldInitializer().initFields(testInstance, gson);
+ }
+
+ /**
+ * {@link JsonTesterFieldInitializer} for Gson.
+ */
+ private static class GsonFieldInitializer extends FieldInitializer {
+
+ protected GsonFieldInitializer() {
+ super(GsonTester.class);
+ }
+
+ @Override
+ protected AbstractJsonMarshalTester createTester(
+ Class> resourceLoadClass, ResolvableType type, Gson marshaller) {
+ return new GsonTester(resourceLoadClass, type, marshaller);
+ }
+
+ }
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/JacksonTester.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JacksonTester.java
new file mode 100644
index 0000000000..b0eec58df0
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JacksonTester.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.core.ResolvableType;
+import org.springframework.util.Assert;
+
+/**
+ * AssertJ based JSON tester backed by Jackson. Usually instantiated via
+ * {@link #initFields(Object, ObjectMapper)}, for example:
+ * public class ExampleObjectJsonTests {
+ *
+ * private JacksonTester<ExampleObject> json;
+ *
+ * @Before
+ * public void setup() {
+ * ObjectMapper objectMapper = new ObjectMapper();
+ * JacksonTester.initFields(this, objectMapper);
+ * }
+ *
+ * @Test
+ * public void testWriteJson() {
+ * ExampleObject object = //...
+ * assertThat(json.write(object)).isEqualToJson("expected.json");
+ * }
+ *
+ * }
+ *
+ *
+ * See {@link AbstractJsonMarshalTester} for more details.
+ *
+ * @param The type under test
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public class JacksonTester extends AbstractJsonMarshalTester {
+
+ private final ObjectMapper objectMapper;
+
+ /**
+ * Create a new {@link JacksonTester} instance.
+ * @param resourceLoadClass the source class used to load resources
+ * @param type the type under test
+ * @param objectMapper the Jackson object mapper
+ */
+ public JacksonTester(Class> resourceLoadClass, ResolvableType type,
+ ObjectMapper objectMapper) {
+ super(resourceLoadClass, type);
+ Assert.notNull(objectMapper, "ObjectMapper must not be null");
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ protected T readObject(InputStream inputStream, ResolvableType type)
+ throws IOException {
+ return this.objectMapper.readValue(inputStream, getType(type));
+ }
+
+ @Override
+ protected T readObject(Reader reader, ResolvableType type) throws IOException {
+ return this.objectMapper.readerFor(getType(type)).readValue(reader);
+ }
+
+ @Override
+ protected String writeObject(T value, ResolvableType type) throws IOException {
+ return this.objectMapper.writerFor(getType(type)).writeValueAsString(value);
+ }
+
+ private JavaType getType(ResolvableType type) {
+ return this.objectMapper.constructType(type.getType());
+ }
+
+ /**
+ * Utility method to initialize {@link JacksonTester} fields. See {@link JacksonTester
+ * class-level documentation} for example usage.
+ * @param testInstance the test instance
+ * @param objectMapper the object mapper
+ * @see #initFields(Object, ObjectMapper)
+ */
+ public static void initFields(Object testInstance, ObjectMapper objectMapper) {
+ new JacksonFieldInitializer().initFields(testInstance, objectMapper);
+ }
+
+ /**
+ * Utility method to initialize {@link JacksonTester} fields. See {@link JacksonTester
+ * class-level documentation} for example usage.
+ * @param testInstance the test instance
+ * @param objectMapperFactory a factory to create the object mapper
+ * @see #initFields(Object, ObjectMapper)
+ */
+ public static void initFields(Object testInstance,
+ ObjectFactory objectMapperFactory) {
+ new JacksonFieldInitializer().initFields(testInstance, objectMapperFactory);
+ }
+
+ /**
+ * {@link JsonTesterFieldInitializer} for Jackson.
+ */
+ private static class JacksonFieldInitializer extends FieldInitializer {
+
+ protected JacksonFieldInitializer() {
+ super(JacksonTester.class);
+ }
+
+ @Override
+ protected AbstractJsonMarshalTester createTester(
+ Class> resourceLoadClass, ResolvableType type,
+ ObjectMapper marshaller) {
+ return new JacksonTester(resourceLoadClass, type, marshaller);
+ }
+
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContent.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContent.java
new file mode 100644
index 0000000000..12469e1205
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContent.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import org.assertj.core.api.AssertProvider;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.util.Assert;
+
+/**
+ * JSON content created usually from a JSON tester. Generally used only to
+ * {@link AssertProvider provide} {@link JsonContentAssert} to AssertJ {@code assertThat}
+ * calls.
+ *
+ * @param The source type that created the content
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public final class JsonContent implements AssertProvider {
+
+ private final Class> resourceLoadClass;
+
+ private final ResolvableType type;
+
+ private final String json;
+
+ /**
+ * Create a new {@link JsonContent} instance.
+ * @param resourceLoadClass the source class used to load resources
+ * @param type the type under test (or {@code null} if not known)
+ * @param json the actual JSON content
+ */
+ public JsonContent(Class> resourceLoadClass, ResolvableType type, String json) {
+ Assert.notNull(resourceLoadClass, "ResourceLoadClass must not be null");
+ Assert.notNull(json, "JSON must not be null");
+ this.resourceLoadClass = resourceLoadClass;
+ this.type = type;
+ this.json = json;
+ }
+
+ @Override
+ public JsonContentAssert assertThat() {
+ return new JsonContentAssert(this.resourceLoadClass, this.json);
+ }
+
+ /**
+ * Return the actual JSON content string.
+ * @return the JSON content
+ */
+ public String getJson() {
+ return this.json;
+ }
+
+ @Override
+ public String toString() {
+ return "JsonContent " + this.json
+ + (this.type == null ? "" : " created from " + this.type);
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java
new file mode 100644
index 0000000000..5cd1e6c13f
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java
@@ -0,0 +1,1173 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import com.jayway.jsonpath.JsonPath;
+import org.assertj.core.api.AbstractAssert;
+import org.assertj.core.api.AbstractBooleanAssert;
+import org.assertj.core.api.AbstractCharSequenceAssert;
+import org.assertj.core.api.AbstractListAssert;
+import org.assertj.core.api.AbstractMapAssert;
+import org.assertj.core.api.AbstractObjectAssert;
+import org.assertj.core.api.Assert;
+import org.assertj.core.api.Assertions;
+import org.skyscreamer.jsonassert.JSONCompare;
+import org.skyscreamer.jsonassert.JSONCompareMode;
+import org.skyscreamer.jsonassert.JSONCompareResult;
+import org.skyscreamer.jsonassert.comparator.JSONComparator;
+
+import org.springframework.core.io.Resource;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * AssertJ {@link Assert} for {@link JsonContent}.
+ *
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public class JsonContentAssert extends AbstractAssert {
+
+ private final JsonLoader loader;
+
+ /**
+ * Create a new {@link JsonContentAssert} instance.
+ * @param resourceLoadClass the source class used to load resources
+ * @param json the actual JSON content
+ */
+ public JsonContentAssert(Class> resourceLoadClass, CharSequence json) {
+ super(json, JsonContentAssert.class);
+ this.loader = new JsonLoader(resourceLoadClass);
+ }
+
+ /**
+ * Overridden version of {@code isEqualTo} to perform JSON tests based on the object
+ * type.
+ * @see org.assertj.core.api.AbstractAssert#isEqualTo(java.lang.Object)
+ */
+ @Override
+ public JsonContentAssert isEqualTo(Object expected) {
+ try {
+ if (expected == null || expected instanceof CharSequence) {
+ return isEqualToJson((CharSequence) expected);
+ }
+ if (expected instanceof byte[]) {
+ return isEqualToJson((byte[]) expected);
+ }
+ if (expected instanceof File) {
+ return isEqualToJson((File) expected);
+ }
+ if (expected instanceof InputStream) {
+ return isEqualToJson((InputStream) expected);
+ }
+ if (expected instanceof Resource) {
+ return isEqualToJson((Resource) expected);
+ }
+ throw new AssertionError(
+ "Unsupport type for JSON assert " + expected.getClass());
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#LENIENT leniently} equal
+ * to the specified JSON. The {@code expected} value can contain the JSON itself or,
+ * if it ends with {@code .json}, the name of a resource to be loaded using
+ * {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(CharSequence expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#LENIENT leniently} equal
+ * to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(String path, Class> resourceLoadClass)
+ throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#LENIENT leniently} equal
+ * to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(byte[] expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#LENIENT leniently} equal
+ * to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(File expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#LENIENT leniently} equal
+ * to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(InputStream expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#LENIENT leniently} equal
+ * to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(Resource expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#STRICT strictly} equal to
+ * the specified JSON. The {@code expected} value can contain the JSON itself or, if
+ * it ends with {@code .json}, the name of a resource to be loaded using
+ * {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isStrictlyEqualToJson(CharSequence expected)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#STRICT strictly} equal to
+ * the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isStrictlyEqualToJson(String path,
+ Class> resourceLoadClass) throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#STRICT strictly} equal to
+ * the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isStrictlyEqualToJson(byte[] expected) throws IOException {
+ return assertNotFailed(
+ compare(this.loader.getJson(expected), JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#STRICT strictly} equal to
+ * the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isStrictlyEqualToJson(File expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#STRICT strictly} equal to
+ * the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isStrictlyEqualToJson(InputStream expected)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is {@link JSONCompareMode#STRICT strictly} equal to
+ * the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isStrictlyEqualToJson(Resource expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON. The {@code expected}
+ * value can contain the JSON itself or, if it ends with {@code .json}, the name of a
+ * resource to be loaded using {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(CharSequence expected,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(String path, Class> resourceLoadClass,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotFailed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(byte[] expected, JSONCompareMode compareMode)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(File expected, JSONCompareMode compareMode)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(InputStream expected,
+ JSONCompareMode compareMode) throws IOException {
+ return assertNotFailed(compare(this.loader.getJson(expected), compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(Resource expected, JSONCompareMode compareMode)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON. The {@code expected}
+ * value can contain the JSON itself or, if it ends with {@code .json}, the name of a
+ * resource to be loaded using {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(CharSequence expected,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(String path, Class> resourceLoadClass,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotFailed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(byte[] expected, JSONComparator comparator)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(File expected, JSONComparator comparator)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(InputStream expected,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is equal to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is not equal to the given one
+ */
+ public JsonContentAssert isEqualToJson(Resource expected, JSONComparator comparator)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotFailed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Overridden version of {@code isNotEqualTo} to perform JSON tests based on the
+ * object type.
+ * @see org.assertj.core.api.AbstractAssert#isEqualTo(java.lang.Object)
+ */
+ @Override
+ public JsonContentAssert isNotEqualTo(Object expected) {
+ try {
+ if (expected == null || expected instanceof CharSequence) {
+ return isNotEqualToJson((CharSequence) expected);
+ }
+ if (expected instanceof byte[]) {
+ return isNotEqualToJson((byte[]) expected);
+ }
+ if (expected instanceof File) {
+ return isNotEqualToJson((File) expected);
+ }
+ if (expected instanceof InputStream) {
+ return isNotEqualToJson((InputStream) expected);
+ }
+ if (expected instanceof Resource) {
+ return isNotEqualToJson((Resource) expected);
+ }
+ throw new AssertionError(
+ "Unsupport type for JSON assert " + expected.getClass());
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#LENIENT leniently}
+ * equal to the specified JSON. The {@code expected} value can contain the JSON itself
+ * or, if it ends with {@code .json}, the name of a resource to be loaded using
+ * {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(CharSequence expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#LENIENT leniently}
+ * equal to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(String path, Class> resourceLoadClass)
+ throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#LENIENT leniently}
+ * equal to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(byte[] expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#LENIENT leniently}
+ * equal to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(File expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#LENIENT leniently}
+ * equal to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(InputStream expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#LENIENT leniently}
+ * equal to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(Resource expected) throws IOException {
+ return assertNotPassed(
+ compare(this.loader.getJson(expected), JSONCompareMode.LENIENT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#STRICT strictly} equal
+ * to the specified JSON. The {@code expected} value can contain the JSON itself or,
+ * if it ends with {@code .json}, the name of a resource to be loaded using
+ * {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotStrictlyEqualToJson(CharSequence expected)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#STRICT strictly} equal
+ * to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotStrictlyEqualToJson(String path,
+ Class> resourceLoadClass) throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#STRICT strictly} equal
+ * to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotStrictlyEqualToJson(byte[] expected)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#STRICT strictly} equal
+ * to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotStrictlyEqualToJson(File expected) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#STRICT strictly} equal
+ * to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotStrictlyEqualToJson(InputStream expected)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is not {@link JSONCompareMode#STRICT strictly} equal
+ * to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotStrictlyEqualToJson(Resource expected)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, JSONCompareMode.STRICT));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON. The
+ * {@code expected} value can contain the JSON itself or, if it ends with
+ * {@code .json}, the name of a resource to be loaded using {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(CharSequence expected,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(String path, Class> resourceLoadClass,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotPassed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(byte[] expected,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(File expected, JSONCompareMode compareMode)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(InputStream expected,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @param compareMode the compare mode used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(Resource expected,
+ JSONCompareMode compareMode) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, compareMode));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON. The
+ * {@code expected} value can contain the JSON itself or, if it ends with
+ * {@code .json}, the name of a resource to be loaded using {@code resourceLoadClass}.
+ * @param expected the expected JSON or the name of a resource containing the expected
+ * JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(CharSequence expected,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON resource.
+ * @param path the name of a resource containing the expected JSON
+ * @param resourceLoadClass the source class used to load the resource
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(String path, Class> resourceLoadClass,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(path, resourceLoadClass);
+ return assertNotPassed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON bytes.
+ * @param expected the expected JSON bytes
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(byte[] expected, JSONComparator comparator)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON file.
+ * @param expected a file containing the expected JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(File expected, JSONComparator comparator)
+ throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON input stream.
+ * @param expected an input stream containing the expected JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(InputStream expected,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verifies that the actual value is not equal to the specified JSON resource.
+ * @param expected a resource containing the expected JSON
+ * @param comparator the comparator used when checking
+ * @return {@code this} assertion object
+ * @throws IOException on IO error
+ * @throws AssertionError if the actual JSON value is equal to the given one
+ */
+ public JsonContentAssert isNotEqualToJson(Resource expected,
+ JSONComparator comparator) throws IOException {
+ String expectedJson = this.loader.getJson(expected);
+ return assertNotPassed(compare(expectedJson, comparator));
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces a non-null result. If
+ * the JSON path expression is not {@linkplain JsonPath#isDefinite() definite}, this
+ * method verifies that the value at the given path is not empty .
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is missing
+ */
+ public JsonContentAssert hasJsonPathValue(CharSequence expression, Object... args) {
+ new JsonPathValue(expression, args).assertHasValue(Object.class, "an object");
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces a non-null string
+ * result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is missing or not a string
+ */
+ public JsonContentAssert hasJsonPathStringValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertHasValue(String.class, "a string");
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces a non-null number
+ * result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is missing or not a number
+ */
+ public JsonContentAssert hasJsonPathNumberValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertHasValue(Number.class, "a number");
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces a non-null boolean
+ * result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is missing or not a boolean
+ */
+ public JsonContentAssert hasJsonPathBooleanValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertHasValue(Boolean.class, "a boolean");
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces a non-null array
+ * result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is missing or not an array
+ */
+ public JsonContentAssert hasJsonPathArrayValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertHasValue(List.class, "an array");
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces a non-null map result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is missing or not a map
+ */
+ public JsonContentAssert hasJsonPathMapValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertHasValue(Map.class, "a map");
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces an
+ * {@link ObjectUtils#isEmpty(Object) empty} result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is not empty
+ */
+ public JsonContentAssert hasEmptyJsonPathValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertHasEmptyValue();
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path produces no result. If the JSON
+ * path expression is not {@linkplain JsonPath#isDefinite() definite}, this method
+ * verifies that the value at the given path is not empty .
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is not missing
+ */
+ public JsonContentAssert doesNotHaveJsonPathValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertDoesNotHaveValue();
+ return this;
+ }
+
+ /**
+ * Verify that the actual value at the given JSON path does not produce an
+ * {@link ObjectUtils#isEmpty(Object) empty} result.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return {@code this} assertion object
+ * @throws AssertionError if the value at the given path is empty
+ */
+ public JsonContentAssert doesNotHaveEmptyJsonPathValue(CharSequence expression,
+ Object... args) {
+ new JsonPathValue(expression, args).assertDoesNotHaveEmptyValue();
+ return this;
+ }
+
+ /**
+ * Extract the value at the given JSON path for further object assertions.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return a new assertion object whose object under test is the extracted item
+ * @throws AssertionError if the path is not valid
+ */
+ public AbstractObjectAssert, Object> extractingJsonPathValue(
+ CharSequence expression, Object... args) {
+ return Assertions.assertThat(new JsonPathValue(expression, args).getValue(false));
+ }
+
+ /**
+ * Extract the string value at the given JSON path for further object assertions.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return a new assertion object whose object under test is the extracted item
+ * @throws AssertionError if the path is not valid or does not result in a string
+ */
+ public AbstractCharSequenceAssert, String> extractingJsonPathStringValue(
+ CharSequence expression, Object... args) {
+ return Assertions.assertThat(
+ extractingJsonPathValue(expression, args, String.class, "a string"));
+ }
+
+ /**
+ * Extract the number value at the given JSON path for further object assertions.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return a new assertion object whose object under test is the extracted item
+ * @throws AssertionError if the path is not valid or does not result in a number
+ */
+ public AbstractObjectAssert, Number> extractingJsonPathNumberValue(
+ CharSequence expression, Object... args) {
+ return Assertions.assertThat(
+ extractingJsonPathValue(expression, args, Number.class, "a number"));
+ }
+
+ /**
+ * Extract the boolean value at the given JSON path for further object assertions.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return a new assertion object whose object under test is the extracted item
+ * @throws AssertionError if the path is not valid or does not result in a boolean
+ */
+ public AbstractBooleanAssert> extractingJsonPathBooleanValue(
+ CharSequence expression, Object... args) {
+ return Assertions.assertThat(
+ extractingJsonPathValue(expression, args, Boolean.class, "a boolean"));
+ }
+
+ /**
+ * Extract the array value at the given JSON path for further object assertions.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return a new assertion object whose object under test is the extracted item
+ * @throws AssertionError if the path is not valid or does not result in an array
+ */
+ @SuppressWarnings("unchecked")
+ public AbstractListAssert, ?, Object> extractingJsonPathArrayValue(
+ CharSequence expression, Object... args) {
+ return Assertions.assertThat(
+ extractingJsonPathValue(expression, args, List.class, "an array"));
+ }
+
+ /**
+ * Extract the map value at the given JSON path for further object assertions.
+ * @param expression the {@link JsonPath} expression
+ * @param args arguments to parameterize the {@code JsonPath} expression with, using
+ * formatting specifiers defined in {@link String#format(String, Object...)}
+ * @return a new assertion object whose object under test is the extracted item
+ * @throws AssertionError if the path is not valid or does not result in a map
+ */
+ @SuppressWarnings("unchecked")
+ public AbstractMapAssert, ?, Object, Object> extractingJsonPathMapValue(
+ CharSequence expression, Object... args) {
+ return Assertions.assertThat(
+ extractingJsonPathValue(expression, args, Map.class, "a map"));
+ }
+
+ @SuppressWarnings("unchecked")
+ private T extractingJsonPathValue(CharSequence expression, Object[] args,
+ Class type, String expectedDescription) {
+ JsonPathValue value = new JsonPathValue(expression, args);
+ if (value.getValue(false) != null) {
+ value.assertHasValue(type, expectedDescription);
+ }
+ return (T) value.getValue(false);
+ }
+
+ private JSONCompareResult compare(CharSequence expectedJson,
+ JSONCompareMode compareMode) {
+ if (this.actual == null) {
+ return compareForNull(expectedJson);
+ }
+ return JSONCompare.compareJSON(
+ (expectedJson == null ? null : expectedJson.toString()),
+ this.actual.toString(), compareMode);
+ }
+
+ private JSONCompareResult compare(CharSequence expectedJson,
+ JSONComparator comparator) {
+ if (this.actual == null) {
+ return compareForNull(expectedJson);
+ }
+ return JSONCompare.compareJSON(
+ (expectedJson == null ? null : expectedJson.toString()),
+ this.actual.toString(), comparator);
+ }
+
+ private JSONCompareResult compareForNull(CharSequence expectedJson) {
+ JSONCompareResult result = new JSONCompareResult();
+ result.passed();
+ if (expectedJson != null) {
+ result.fail("Expected non-null JSON");
+ }
+ return result;
+ }
+
+ private JsonContentAssert assertNotFailed(JSONCompareResult result) {
+ if (result.failed()) {
+ throw new AssertionError("JSON Comparison failure: " + result.getMessage());
+ }
+ return this;
+ }
+
+ private JsonContentAssert assertNotPassed(JSONCompareResult result) {
+ if (result.passed()) {
+ throw new AssertionError("JSON Comparison failure: " + result.getMessage());
+ }
+ return this;
+ }
+
+ /**
+ * A {@link JsonPath} value.
+ */
+ private class JsonPathValue {
+
+ private final String expression;
+
+ private final JsonPath jsonPath;
+
+ JsonPathValue(CharSequence expression, Object... args) {
+ org.springframework.util.Assert.hasText(
+ (expression == null ? null : expression.toString()),
+ "expression must not be null or empty");
+ this.expression = String.format(expression.toString(), args);
+ this.jsonPath = JsonPath.compile(this.expression);
+ }
+
+ public void assertHasEmptyValue() {
+ if (ObjectUtils.isEmpty(getValue(false)) || isIndefiniteAndEmpty()) {
+ return;
+ }
+ throw new AssertionError(getExpectedValueMessage("an empty value"));
+ }
+
+ public void assertDoesNotHaveEmptyValue() {
+ if (!ObjectUtils.isEmpty(getValue(false))) {
+ return;
+ }
+ throw new AssertionError(getExpectedValueMessage("a non-empty value"));
+
+ }
+
+ public void assertHasValue(Class> type, String expectedDescription) {
+ Object value = getValue(true);
+ if (value == null || isIndefiniteAndEmpty()) {
+ throw new AssertionError(getNoValueMessage());
+ }
+ if (type != null && !type.isInstance(value)) {
+ throw new AssertionError(getExpectedValueMessage(expectedDescription));
+ }
+ }
+
+ public void assertDoesNotHaveValue() {
+ if (getValue(false) == null || isIndefiniteAndEmpty()) {
+ return;
+ }
+ throw new AssertionError(getExpectedValueMessage("no value"));
+ }
+
+ private boolean isIndefiniteAndEmpty() {
+ return !isDefinite() && isEmpty();
+ }
+
+ private boolean isDefinite() {
+ return this.jsonPath.isDefinite();
+ }
+
+ private boolean isEmpty() {
+ return ObjectUtils.isEmpty(getValue(false));
+ }
+
+ public Object getValue(boolean required) {
+ try {
+ CharSequence json = JsonContentAssert.this.actual;
+ return this.jsonPath.read(json == null ? null : json.toString());
+ }
+ catch (Exception ex) {
+ if (!required) {
+ return null;
+ }
+ throw new AssertionError(getNoValueMessage() + ex.getMessage());
+ }
+ }
+
+ private String getNoValueMessage() {
+ return "No value at JSON path \"" + this.expression + "\"";
+ }
+
+ private String getExpectedValueMessage(String expectedDescription) {
+ return String.format("Expected %s at JSON path \"%s\" but found: %s",
+ expectedDescription, this.expression, ObjectUtils.nullSafeToString(
+ StringUtils.quoteIfString(getValue(false))));
+ }
+
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonLoader.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonLoader.java
new file mode 100644
index 0000000000..acb987a1d7
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonLoader.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.util.FileCopyUtils;
+
+/**
+ * Internal helper used to load JSON from various sources.
+ *
+ * @author Phillip Webb
+ */
+class JsonLoader {
+
+ private final Class> resourceLoadClass;
+
+ JsonLoader(Class> resourceLoadClass) {
+ this.resourceLoadClass = resourceLoadClass;
+ }
+
+ public Class> getResourceLoadClass() {
+ return this.resourceLoadClass;
+ }
+
+ public String getJson(CharSequence source) throws IOException {
+ if (source == null) {
+ return null;
+ }
+ if (source.toString().endsWith(".json")) {
+ return getJson(
+ new ClassPathResource(source.toString(), this.resourceLoadClass));
+ }
+ return source.toString();
+ }
+
+ public String getJson(String path, Class> resourceLoadClass) throws IOException {
+ return getJson(new ClassPathResource(path, resourceLoadClass));
+ }
+
+ public String getJson(byte[] source) throws IOException {
+ return getJson(new ByteArrayInputStream(source));
+ }
+
+ public String getJson(File source) throws IOException {
+ return getJson(new FileInputStream(source));
+ }
+
+ public String getJson(Resource source) throws IOException {
+ return getJson(source.getInputStream());
+ }
+
+ public String getJson(InputStream source) throws IOException {
+ return FileCopyUtils.copyToString(new InputStreamReader(source));
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/ObjectContent.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/ObjectContent.java
new file mode 100644
index 0000000000..4977835366
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/ObjectContent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import org.assertj.core.api.AssertProvider;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.util.Assert;
+
+/**
+ * Object content usually created from {@link AbstractJsonMarshalTester}.Generally used
+ * only to {@link AssertProvider provide} {@link ObjectContentAssert} to AssertJ
+ * {@code assertThat} calls.
+ *
+ * @param The content type
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public final class ObjectContent implements AssertProvider> {
+
+ private final ResolvableType type;
+
+ private final T object;
+
+ /**
+ * Create a new {@link ObjectContent} instance.
+ * @param type the type under test (or {@code null} if not known)
+ * @param object the actual object content
+ */
+ public ObjectContent(ResolvableType type, T object) {
+ Assert.notNull(object, "Object must not be null");
+ this.type = type;
+ this.object = object;
+ }
+
+ @Override
+ public ObjectContentAssert assertThat() {
+ return new ObjectContentAssert(this.object);
+ }
+
+ /**
+ * Return the actual object content.
+ * @return the object content
+ */
+ public T getObject() {
+ return this.object;
+ }
+
+ @Override
+ public String toString() {
+ return "ObjectContent " + this.object
+ + (this.type == null ? "" : " created from " + this.type);
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/ObjectContentAssert.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/ObjectContentAssert.java
new file mode 100644
index 0000000000..e07e7627b8
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/ObjectContentAssert.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.util.Map;
+
+import org.assertj.core.api.AbstractMapAssert;
+import org.assertj.core.api.AbstractObjectArrayAssert;
+import org.assertj.core.api.AbstractObjectAssert;
+import org.assertj.core.api.Assert;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.internal.Objects;
+
+/**
+ * AssertJ {@link Assert} for {@link JsonContent}.
+ *
+ * @param The actual type
+ * @author Phillip Webb
+ * @since 1.4.0
+ */
+public class ObjectContentAssert
+ extends AbstractObjectAssert, A> {
+
+ protected ObjectContentAssert(A actual) {
+ super(actual, ObjectContentAssert.class);
+ }
+
+ /**
+ * Verifies that the actual value is an array, and returns an array assertion, to
+ * allow chaining of array-specific assertions from this call.
+ * @return a list assertion object
+ */
+ public AbstractObjectArrayAssert, Object> asArray() {
+ Objects.instance().assertIsInstanceOf(this.info, this.actual, Object[].class);
+ return Assertions.assertThat((Object[]) this.actual);
+ }
+
+ /**
+ * Verifies that the actual value is a map, and returns a map assertion, to allow
+ * chaining of list-specific assertions from this call.
+ * @return a list assertion object
+ */
+ @SuppressWarnings("unchecked")
+ public AbstractMapAssert, ?, Object, Object> asMap() {
+ Objects.instance().assertIsInstanceOf(this.info, this.actual, Map.class);
+ return Assertions.assertThat((Map) this.actual);
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/json/package-info.java b/spring-boot-test/src/main/java/org/springframework/boot/test/json/package-info.java
new file mode 100644
index 0000000000..1bbb095433
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/json/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-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.
+ */
+
+/**
+ * Support for testing JSON.
+ */
+package org.springframework.boot.test.json;
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java
new file mode 100644
index 0000000000..3239d24459
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.ReflectionUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link AbstractJsonMarshalTester}.
+ *
+ * @author Phillip Webb
+ */
+public abstract class AbstractJsonMarshalTesterTests {
+
+ private static final String JSON = "{\"name\":\"Spring\",\"age\":123}";
+
+ private static final String MAP_JSON = "{\"a\":" + JSON + "}";
+
+ private static final String ARRAY_JSON = "[" + JSON + "]";
+
+ private static final ExampleObject OBJECT = createExampleObject("Spring", 123);
+
+ private static final ResolvableType TYPE = ResolvableType
+ .forClass(ExampleObject.class);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void writeShouldReturnJsonContent() throws Exception {
+ JsonContent content = createTester(TYPE).write(OBJECT);
+ assertThat(content).isEqualToJson(JSON);
+ }
+
+ @Test
+ public void writeListShouldReturnJsonContent() throws Exception {
+ ResolvableType type = ResolvableTypes.get("listOfExampleObject");
+ List value = Collections.singletonList(OBJECT);
+ JsonContent content = createTester(type).write(value);
+ assertThat(content).isEqualToJson(ARRAY_JSON);
+ }
+
+ @Test
+ public void writeArrayShouldReturnJsonContent() throws Exception {
+ ResolvableType type = ResolvableTypes.get("arrayOfExampleObject");
+ ExampleObject[] value = new ExampleObject[] { OBJECT };
+ JsonContent content = createTester(type).write(value);
+ assertThat(content).isEqualToJson(ARRAY_JSON);
+ }
+
+ @Test
+ public void writeMapShouldReturnJsonContent() throws Exception {
+ ResolvableType type = ResolvableTypes.get("mapOfExampleObject");
+ Map value = new LinkedHashMap();
+ value.put("a", OBJECT);
+ JsonContent content = createTester(type).write(value);
+ assertThat(content).isEqualToJson(MAP_JSON);
+ }
+
+ @Test
+ public void createWhenResourceLoadClassIsNullShouldThrowException() throws Exception {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("ResourceLoadClass must not be null");
+ createTester(null, ResolvableType.forClass(ExampleObject.class));
+ }
+
+ @Test
+ public void createWhenTypeIsNullShouldThrowException() throws Exception {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Type must not be null");
+ createTester(getClass(), null);
+ }
+
+ @Test
+ public void parseBytesShouldReturnObject() throws Exception {
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.parse(JSON.getBytes())).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void parseStringShouldReturnObject() throws Exception {
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.parse(JSON)).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void readResourcePathShouldReturnObject() throws Exception {
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.read("example.json")).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void readFileShouldReturnObject() throws Exception {
+ File file = this.temp.newFile("example.json");
+ FileCopyUtils.copy(JSON.getBytes(), file);
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.read(file)).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void readInputStreamShouldReturnObject() throws Exception {
+ InputStream stream = new ByteArrayInputStream(JSON.getBytes());
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.read(stream)).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void readResourceShouldReturnObject() throws Exception {
+ Resource resource = new ByteArrayResource(JSON.getBytes());
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.read(resource)).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void readReaderShouldReturnObject() throws Exception {
+ Reader reader = new StringReader(JSON);
+ AbstractJsonMarshalTester tester = createTester(TYPE);
+ assertThat(tester.read(reader)).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void parseListShouldReturnContent() throws Exception {
+ ResolvableType type = ResolvableTypes.get("listOfExampleObject");
+ AbstractJsonMarshalTester tester = createTester(type);
+ assertThat(tester.parse(ARRAY_JSON)).asList().containsOnly(OBJECT);
+ }
+
+ @Test
+ public void parseArrayShouldReturnContent() throws Exception {
+ ResolvableType type = ResolvableTypes.get("arrayOfExampleObject");
+ AbstractJsonMarshalTester tester = createTester(type);
+ assertThat(tester.parse(ARRAY_JSON)).asArray().containsOnly(OBJECT);
+ }
+
+ @Test
+ public void parseMapShouldReturnContent() throws Exception {
+ ResolvableType type = ResolvableTypes.get("mapOfExampleObject");
+ AbstractJsonMarshalTester tester = createTester(type);
+ assertThat(tester.parse(MAP_JSON)).asMap().containsEntry("a", OBJECT);
+ }
+
+ protected static final ExampleObject createExampleObject(String name, int age) {
+ ExampleObject exampleObject = new ExampleObject();
+ exampleObject.setName(name);
+ exampleObject.setAge(age);
+ return exampleObject;
+ }
+
+ protected final AbstractJsonMarshalTester createTester(ResolvableType type) {
+ return createTester(AbstractJsonMarshalTesterTests.class, type);
+ }
+
+ protected abstract AbstractJsonMarshalTester createTester(
+ Class> resourceLoadClass, ResolvableType type);
+
+ /**
+ * Access to field backed {@link ResolvableType}.
+ */
+ public static class ResolvableTypes {
+
+ public List listOfExampleObject;
+
+ public ExampleObject[] arrayOfExampleObject;
+
+ public Map mapOfExampleObject;
+
+ public static ResolvableType get(String name) {
+ Field field = ReflectionUtils.findField(ResolvableTypes.class, name);
+ return ResolvableType.forField(field);
+ }
+
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/BasicJsonTesterTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/BasicJsonTesterTests.java
new file mode 100644
index 0000000000..a255b239ad
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/BasicJsonTesterTests.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.util.FileCopyUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link BasicJsonTester}.
+ *
+ * @author Phillip Webb
+ */
+public class BasicJsonTesterTests {
+
+ private static final String JSON = "{\"spring\":[\"boot\",\"framework\"]}";
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ private BasicJsonTester json = new BasicJsonTester(getClass());
+
+ @Test
+ public void createWhenResourceLoadClassIsNullShouldThrowException() throws Exception {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("ResourceLoadClass must not be null");
+ new BasicJsonTester(null);
+ }
+
+ @Test
+ public void fromJsonStringShouldReturnJsonContent() throws Exception {
+ assertThat(this.json.from(JSON)).isEqualToJson("source.json");
+ }
+
+ @Test
+ public void fromResourceStringShouldReturnJsonContent() throws Exception {
+ assertThat(this.json.from("source.json")).isEqualToJson(JSON);
+ }
+
+ @Test
+ public void fromResourceStringWithClassShouldReturnJsonContent() throws Exception {
+ assertThat(this.json.from("source.json", getClass())).isEqualToJson(JSON);
+ }
+
+ @Test
+ public void fromByteArrayShouldReturnJsonContent() throws Exception {
+ assertThat(this.json.from(JSON.getBytes())).isEqualToJson("source.json");
+ }
+
+ @Test
+ public void fromFileShouldReturnJsonContent() throws Exception {
+ File file = this.tempFolder.newFile("file.json");
+ FileCopyUtils.copy(JSON.getBytes(), file);
+ assertThat(this.json.from(file)).isEqualToJson("source.json");
+ }
+
+ @Test
+ public void fromInputStreamShouldReturnJsonContent() throws Exception {
+ InputStream inputStream = new ByteArrayInputStream(JSON.getBytes());
+ assertThat(this.json.from(inputStream)).isEqualToJson("source.json");
+ }
+
+ @Test
+ public void fromResourceShouldReturnJsonContent() throws Exception {
+ Resource resource = new ByteArrayResource(JSON.getBytes());
+ assertThat(this.json.from(resource)).isEqualToJson("source.json");
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/ExampleObject.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/ExampleObject.java
new file mode 100644
index 0000000000..9ad5a00d49
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/ExampleObject.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import org.springframework.util.ObjectUtils;
+
+/**
+ * Example object used for serialization.
+ */
+public class ExampleObject {
+
+ private String name;
+
+ private int age;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return this.age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+ ExampleObject other = (ExampleObject) obj;
+ return ObjectUtils.nullSafeEquals(this.name, other.name)
+ && ObjectUtils.nullSafeEquals(this.age, other.age);
+ }
+
+ @Override
+ public String toString() {
+ return this.name + " " + this.age;
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/GsonTesterTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/GsonTesterTests.java
new file mode 100644
index 0000000000..6ff222b07e
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/GsonTesterTests.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.util.List;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.junit.Test;
+
+import org.springframework.core.ResolvableType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link GsonTester}.
+ *
+ * @author Phillip Webb
+ */
+public class GsonTesterTests extends AbstractJsonMarshalTesterTests {
+
+ @Test
+ public void initFieldsWhenTestIsNullShouldThrowException() {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("TestInstance must not be null");
+ GsonTester.initFields(null, new GsonBuilder().create());
+ }
+
+ @Test
+ public void initFieldsWhenObjectMapperIsNullShouldThrowException() {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Marshaller must not be null");
+ GsonTester.initFields(new InitFieldsTestClass(), (Gson) null);
+ }
+
+ @Test
+ public void initFieldsShouldSetNullFields() {
+ InitFieldsTestClass test = new InitFieldsTestClass();
+ assertThat(test.test).isNull();
+ assertThat(test.base).isNull();
+ GsonTester.initFields(test, new GsonBuilder().create());
+ assertThat(test.test).isNotNull();
+ assertThat(test.base).isNotNull();
+ assertThat(test.test.getType().resolve()).isEqualTo(List.class);
+ assertThat(test.test.getType().resolveGeneric()).isEqualTo(ExampleObject.class);
+ }
+
+ @Override
+ protected AbstractJsonMarshalTester createTester(Class> resourceLoadClass,
+ ResolvableType type) {
+ return new GsonTester(resourceLoadClass, type,
+ new GsonBuilder().create());
+ }
+
+ static abstract class InitFieldsBaseClass {
+
+ public GsonTester base;
+
+ public GsonTester baseSet = new GsonTester(
+ InitFieldsBaseClass.class, ResolvableType.forClass(ExampleObject.class),
+ new GsonBuilder().create());
+
+ }
+
+ static class InitFieldsTestClass extends InitFieldsBaseClass {
+
+ public GsonTester> test;
+
+ public GsonTester testSet = new GsonTester(
+ InitFieldsBaseClass.class, ResolvableType.forClass(ExampleObject.class),
+ new GsonBuilder().create());
+
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterIntegrationTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterIntegrationTests.java
new file mode 100644
index 0000000000..f85532cad2
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterIntegrationTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration tests for {@link JacksonTester}. Shows typical usage.
+ *
+ * @author Phillip Webb
+ */
+public class JacksonTesterIntegrationTests {
+
+ private JacksonTester> listJson;
+
+ private JacksonTester> mapJson;
+
+ @Before
+ public void setup() {
+ JacksonTester.initFields(this, new ObjectMapper());
+ }
+
+ @Test
+ public void typicalListTest() throws Exception {
+ String example = "[{\"name\":\"Spring\",\"age\":123}]";
+ assertThat(this.listJson.parse(example)).asList().hasSize(1);
+ assertThat(this.listJson.parse(example).getObject().get(0).getName())
+ .isEqualTo("Spring");
+ }
+
+ @Test
+ public void typicalMapTest() throws Exception {
+ Map map = new LinkedHashMap();
+ map.put("a", 1);
+ map.put("b", 2);
+ assertThat(this.mapJson.write(map)).extractingJsonPathNumberValue("@.a")
+ .isEqualTo(1);
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterTests.java
new file mode 100644
index 0000000000..dc28dbf57b
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.util.List;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+import org.springframework.core.ResolvableType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link JacksonTester}.
+ *
+ * @author Phillip Webb
+ */
+public class JacksonTesterTests extends AbstractJsonMarshalTesterTests {
+
+ @Test
+ public void initFieldsWhenTestIsNullShouldThrowException() {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("TestInstance must not be null");
+ JacksonTester.initFields(null, new ObjectMapper());
+ }
+
+ @Test
+ public void initFieldsWhenObjectMapperIsNullShouldThrowException() {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Marshaller must not be null");
+ JacksonTester.initFields(new InitFieldsTestClass(), (ObjectMapper) null);
+ }
+
+ @Test
+ public void initFieldsShouldSetNullFields() {
+ InitFieldsTestClass test = new InitFieldsTestClass();
+ assertThat(test.test).isNull();
+ assertThat(test.base).isNull();
+ JacksonTester.initFields(test, new ObjectMapper());
+ assertThat(test.test).isNotNull();
+ assertThat(test.base).isNotNull();
+ assertThat(test.test.getType().resolve()).isEqualTo(List.class);
+ assertThat(test.test.getType().resolveGeneric()).isEqualTo(ExampleObject.class);
+ }
+
+ @Override
+ protected AbstractJsonMarshalTester createTester(Class> resourceLoadClass,
+ ResolvableType type) {
+ return new JacksonTester(resourceLoadClass, type, new ObjectMapper());
+ }
+
+ static abstract class InitFieldsBaseClass {
+
+ public JacksonTester base;
+
+ public JacksonTester baseSet = new JacksonTester(
+ InitFieldsBaseClass.class, ResolvableType.forClass(ExampleObject.class),
+ new ObjectMapper());
+
+ }
+
+ static class InitFieldsTestClass extends InitFieldsBaseClass {
+
+ public JacksonTester> test;
+
+ public JacksonTester testSet = new JacksonTester(
+ InitFieldsBaseClass.class, ResolvableType.forClass(ExampleObject.class),
+ new ObjectMapper());
+
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/JsonContentAssertTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JsonContentAssertTests.java
new file mode 100644
index 0000000000..fd8f4c2ad8
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JsonContentAssertTests.java
@@ -0,0 +1,1339 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.assertj.core.api.AssertProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.skyscreamer.jsonassert.JSONCompareMode;
+import org.skyscreamer.jsonassert.comparator.DefaultComparator;
+import org.skyscreamer.jsonassert.comparator.JSONComparator;
+
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.test.util.JsonPathExpectationsHelper;
+import org.springframework.util.FileCopyUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link JsonContentAssert}. Some tests here are based on Spring Framework
+ * tests for {@link JsonPathExpectationsHelper}.
+ *
+ * @author Phillip Webb
+ */
+public class JsonContentAssertTests {
+
+ private static final String SOURCE = loadJson("source.json");
+
+ private static final String LENIENT_SAME = loadJson("lenient-same.json");
+
+ private static final String DIFFERENT = loadJson("different.json");
+
+ private static final String TYPES = loadJson("types.json");
+
+ private static final String SIMPSONS = loadJson("simpsons.json");
+
+ private static JSONComparator COMPARATOR = new DefaultComparator(
+ JSONCompareMode.LENIENT);
+
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Test
+ public void isEqualToWhenStringIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(LENIENT_SAME);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenNullActualShouldFail() throws Exception {
+ assertThat(forJson(null)).isEqualTo(SOURCE);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenStringIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(DIFFERENT);
+ }
+
+ @Test
+ public void isEqualToWhenResourcePathIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo("lenient-same.json");
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenResourcePathIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo("different.json");
+ }
+
+ @Test
+ public void isEqualToWhenBytesAreMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(LENIENT_SAME.getBytes());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenBytesAreNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(DIFFERENT.getBytes());
+ }
+
+ @Test
+ public void isEqualToWhenFileIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(createFile(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenFileIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(createFile(DIFFERENT));
+ }
+
+ @Test
+ public void isEqualToWhenInputStreamIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(createInputStream(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenInputStreamIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(createInputStream(DIFFERENT));
+ }
+
+ @Test
+ public void isEqualToWhenResourceIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(createResource(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenResourceIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualTo(createResource(DIFFERENT));
+ }
+
+ @Test
+ public void isEqualToJsonWhenStringIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(LENIENT_SAME);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenNullActualShouldFail() throws Exception {
+ assertThat(forJson(null)).isEqualToJson(SOURCE);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenStringIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(DIFFERENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourcePathIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("lenient-same.json");
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourcePathIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("different.json");
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourcePathAndClassIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("lenient-same.json", getClass());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourcePathAndClassIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("different.json", getClass());
+ }
+
+ @Test
+ public void isEqualToJsonWhenBytesAreMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(LENIENT_SAME.getBytes());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenBytesAreNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(DIFFERENT.getBytes());
+ }
+
+ @Test
+ public void isEqualToJsonWhenFileIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createFile(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenFileIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createFile(DIFFERENT));
+ }
+
+ @Test
+ public void isEqualToJsonWhenInputStreamIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createInputStream(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenInputStreamIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createInputStream(DIFFERENT));
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourceIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createResource(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourceIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createResource(DIFFERENT));
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenStringIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(SOURCE);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenStringIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(LENIENT_SAME);
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenResourcePathIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson("source.json");
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenResourcePathIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson("lenient-same.json");
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenResourcePathAndClassIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson("source.json", getClass());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenResourcePathAndClassIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson("lenient-same.json",
+ getClass());
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenBytesAreMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(SOURCE.getBytes());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenBytesAreNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(LENIENT_SAME.getBytes());
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenFileIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(createFile(SOURCE));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenFileIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(createFile(LENIENT_SAME));
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenInputStreamIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(createInputStream(SOURCE));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenInputStreamIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE))
+ .isStrictlyEqualToJson(createInputStream(LENIENT_SAME));
+ }
+
+ @Test
+ public void isStrictlyEqualToJsonWhenResourceIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(createResource(SOURCE));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isStrictlyEqualToJsonWhenResourceIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isStrictlyEqualToJson(createResource(LENIENT_SAME));
+ }
+
+ @Test
+ public void isEqualToJsonWhenStringIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(LENIENT_SAME, JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenStringIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(DIFFERENT, JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourcePathIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("lenient-same.json",
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourcePathIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("different.json",
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourcePathAndClassIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("lenient-same.json", getClass(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourcePathAndClassIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("different.json", getClass(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenBytesAreMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(LENIENT_SAME.getBytes(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenBytesAreNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(DIFFERENT.getBytes(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenFileIsMatchingAndLienientShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createFile(LENIENT_SAME),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenFileIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createFile(DIFFERENT),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenInputStreamIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createInputStream(LENIENT_SAME),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenInputStreamIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createInputStream(DIFFERENT),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourceIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createResource(LENIENT_SAME),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourceIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createResource(DIFFERENT),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isEqualToJsonWhenStringIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(LENIENT_SAME,
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenStringIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(DIFFERENT,
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourcePathIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("lenient-same.json",
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourcePathIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("different.json",
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourcePathAndClassIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("lenient-same.json", getClass(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourcePathAndClassIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson("different.json", getClass(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isEqualToJsonWhenBytesAreMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(LENIENT_SAME.getBytes(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenBytesAreNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(DIFFERENT.getBytes(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isEqualToJsonWhenFileIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createFile(LENIENT_SAME),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenFileIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createFile(DIFFERENT),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isEqualToJsonWhenInputStreamIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createInputStream(LENIENT_SAME),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenInputStreamIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createInputStream(DIFFERENT),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isEqualToJsonWhenResourceIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createResource(LENIENT_SAME),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToJsonWhenResourceIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isEqualToJson(createResource(DIFFERENT),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToWhenStringIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(LENIENT_SAME);
+ }
+
+ @Test
+ public void isNotEqualToWhenNullActualShouldPass() throws Exception {
+ assertThat(forJson(null)).isNotEqualTo(SOURCE);
+ }
+
+ @Test
+ public void isNotEqualToWhenStringIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(DIFFERENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToWhenResourcePathIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo("lenient-same.json");
+ }
+
+ @Test
+ public void isNotEqualToWhenResourcePathIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo("different.json");
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToWhenBytesAreMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(LENIENT_SAME.getBytes());
+ }
+
+ @Test
+ public void isNotEqualToWhenBytesAreNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(DIFFERENT.getBytes());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToWhenFileIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(createFile(LENIENT_SAME));
+ }
+
+ @Test
+ public void isNotEqualToWhenFileIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(createFile(DIFFERENT));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToWhenInputStreamIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(createInputStream(LENIENT_SAME));
+ }
+
+ @Test
+ public void isNotEqualToWhenInputStreamIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(createInputStream(DIFFERENT));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToWhenResourceIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(createResource(LENIENT_SAME));
+ }
+
+ @Test
+ public void isNotEqualToWhenResourceIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualTo(createResource(DIFFERENT));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenStringIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(LENIENT_SAME);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenNullActualShouldPass() throws Exception {
+ assertThat(forJson(null)).isNotEqualToJson(SOURCE);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenStringIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(DIFFERENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourcePathIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("lenient-same.json");
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourcePathIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("different.json");
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourcePathAndClassIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("lenient-same.json", getClass());
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourcePathAndClassIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("different.json", getClass());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenBytesAreMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(LENIENT_SAME.getBytes());
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenBytesAreNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(DIFFERENT.getBytes());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenFileIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createFile(LENIENT_SAME));
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenFileIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createFile(DIFFERENT));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenInputStreamIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createInputStream(LENIENT_SAME));
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenInputStreamIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createInputStream(DIFFERENT));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourceIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(LENIENT_SAME));
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourceIsNotMatchingShouldFail() throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(DIFFERENT));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenStringIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(SOURCE);
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenStringIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(LENIENT_SAME);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenResourcePathIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson("source.json");
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenResourcePathIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson("lenient-same.json");
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenResourcePathAndClassIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson("source.json", getClass());
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenResourcePathAndClassIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson("lenient-same.json",
+ getClass());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenBytesAreMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(SOURCE.getBytes());
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenBytesAreNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(LENIENT_SAME.getBytes());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenFileIsMatchingShouldPass() throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(createFile(SOURCE));
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenFileIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(createFile(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenInputStreamIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(createInputStream(SOURCE));
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenInputStreamIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE))
+ .isNotStrictlyEqualToJson(createInputStream(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotStrictlyEqualToJsonWhenResourceIsMatchingShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotStrictlyEqualToJson(createResource(SOURCE));
+ }
+
+ @Test
+ public void isNotStrictlyEqualToJsonWhenResourceIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE))
+ .isNotStrictlyEqualToJson(createResource(LENIENT_SAME));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenStringIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(LENIENT_SAME,
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenStringIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(DIFFERENT, JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourcePathIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("lenient-same.json",
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourcePathIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("different.json",
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourcePathAndClassIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("lenient-same.json", getClass(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourcePathAndClassIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("different.json", getClass(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenBytesAreMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(LENIENT_SAME.getBytes(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenBytesAreNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(DIFFERENT.getBytes(),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenFileIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createFile(LENIENT_SAME),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenFileIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createFile(DIFFERENT),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenInputStreamIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createInputStream(LENIENT_SAME),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenInputStreamIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createInputStream(DIFFERENT),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourceIsMatchingAndLienientShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(LENIENT_SAME),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourceIsNotMatchingAndLienientShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(DIFFERENT),
+ JSONCompareMode.LENIENT);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenStringIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(LENIENT_SAME,
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenStringIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(DIFFERENT,
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourcePathIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("lenient-same.json",
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourcePathIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("different.json",
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourcePathIsMatchingAndClassAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("lenient-same.json", getClass(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourcePathAndClassAndComparatorIsNotMatchingShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson("different.json", getClass(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenBytesAreMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(LENIENT_SAME.getBytes(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenBytesAreNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(DIFFERENT.getBytes(),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenFileIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createFile(LENIENT_SAME),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenFileIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createFile(DIFFERENT),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenInputStreamIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createInputStream(LENIENT_SAME),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenInputStreamIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createInputStream(DIFFERENT),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isNotEqualToJsonWhenResourceIsMatchingAndComparatorShouldPass()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(LENIENT_SAME),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void isNotEqualToJsonWhenResourceIsNotMatchingAndComparatorShouldFail()
+ throws Exception {
+ assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(DIFFERENT),
+ JsonContentAssertTests.COMPARATOR);
+ }
+
+ @Test
+ public void hasJsonPathValue() throws Exception {
+ System.out.println(TYPES.replace("'", "\""));
+ System.out.println(SIMPSONS.replace("'", "\""));
+ assertThat(forJson(TYPES)).hasJsonPathValue("$.str");
+ }
+
+ @Test
+ public void hasJsonPathValueForAnEmptyArray() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathValue("$.emptyArray");
+ }
+
+ @Test
+ public void hasJsonPathValueForAnEmptyMap() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathValue("$.emptyMap");
+ }
+
+ @Test
+ public void hasJsonPathValueForIndefinatePathWithResults() throws Exception {
+ assertThat(forJson(SIMPSONS))
+ .hasJsonPathValue("$.familyMembers[?(@.name == 'Bart')]");
+ }
+
+ @Test
+ public void hasJsonPathValueForIndefinatePathWithEmptyResults() throws Exception {
+ String expression = "$.familyMembers[?(@.name == 'Dilbert')]";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("No value at JSON path \"" + expression + "\"");
+ assertThat(forJson(SIMPSONS)).hasJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveJsonPathValue() throws Exception {
+ assertThat(forJson(TYPES)).doesNotHaveJsonPathValue("$.bogus");
+ }
+
+ @Test
+ public void doesNotHaveJsonPathValueForAnEmptyArray() throws Exception {
+ String expression = "$.emptyArray";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected no value at JSON path \"" + expression + "\" but found: []");
+ assertThat(forJson(TYPES)).doesNotHaveJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveJsonPathValueForAnEmptyMap() throws Exception {
+ String expression = "$.emptyMap";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected no value at JSON path \"" + expression + "\" but found: {}");
+ assertThat(forJson(TYPES)).doesNotHaveJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveJsonPathValueForIndefinatePathWithResults() throws Exception {
+ String expression = "$.familyMembers[?(@.name == 'Bart')]";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected no value at JSON path \"" + expression
+ + "\" but found: [{\"name\":\"Bart\"}]");
+ assertThat(forJson(SIMPSONS)).doesNotHaveJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveJsonPathValueForIndefinatePathWithEmptyResults()
+ throws Exception {
+ assertThat(forJson(SIMPSONS))
+ .doesNotHaveJsonPathValue("$.familyMembers[?(@.name == 'Dilbert')]");
+ }
+
+ @Test
+ public void hasEmptyJsonPathValueForAnEmptyString() throws Exception {
+ assertThat(forJson(TYPES)).hasEmptyJsonPathValue("$.emptyString");
+ }
+
+ @Test
+ public void hasEmptyJsonPathValueForAnEmptyArray() throws Exception {
+ assertThat(forJson(TYPES)).hasEmptyJsonPathValue("$.emptyArray");
+ }
+
+ @Test
+ public void hasEmptyJsonPathValueForAnEmptyMap() throws Exception {
+ assertThat(forJson(TYPES)).hasEmptyJsonPathValue("$.emptyMap");
+ }
+
+ @Test
+ public void hasEmptyJsonPathValueForIndefinatePathWithEmptyResults()
+ throws Exception {
+ assertThat(forJson(SIMPSONS))
+ .hasEmptyJsonPathValue("$.familyMembers[?(@.name == 'Dilbert')]");
+ }
+
+ @Test
+ public void hasEmptyJsonPathValueForIndefinatePathWithResults() throws Exception {
+ String expression = "$.familyMembers[?(@.name == 'Bart')]";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected an empty value at JSON path \"" + expression
+ + "\" but found: [{\"name\":\"Bart\"}]");
+ assertThat(forJson(SIMPSONS)).hasEmptyJsonPathValue(expression);
+ }
+
+ @Test
+ public void hasEmptyJsonPathValueForWhitespace() throws Exception {
+ String expression = "$.whitespace";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected an empty value at JSON path \"" + expression
+ + "\" but found: ' '");
+ assertThat(forJson(TYPES)).hasEmptyJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForString() throws Exception {
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue("$.str");
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForNumber() throws Exception {
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue("$.num");
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForBoolean() throws Exception {
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue("$.bool");
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForArray() throws Exception {
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue("$.arr");
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForMap() throws Exception {
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue("$.colorMap");
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForIndefinatePathWithResults()
+ throws Exception {
+ assertThat(forJson(SIMPSONS))
+ .doesNotHaveEmptyJsonPathValue("$.familyMembers[?(@.name == 'Bart')]");
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForIndefinatePathWithEmptyResults()
+ throws Exception {
+ String expression = "$.familyMembers[?(@.name == 'Dilbert')]";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected a non-empty value at JSON path \""
+ + expression + "\" but found: []");
+ assertThat(forJson(SIMPSONS)).doesNotHaveEmptyJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForAnEmptyString() throws Exception {
+ String expression = "$.emptyString";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected a non-empty value at JSON path \""
+ + expression + "\" but found: ''");
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForForAnEmptyArray() throws Exception {
+ String expression = "$.emptyArray";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected a non-empty value at JSON path \""
+ + expression + "\" but found: []");
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue(expression);
+ }
+
+ @Test
+ public void doesNotHaveEmptyJsonPathValueForAnEmptyMap() throws Exception {
+ String expression = "$.emptyMap";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected a non-empty value at JSON path \""
+ + expression + "\" but found: {}");
+ assertThat(forJson(TYPES)).doesNotHaveEmptyJsonPathValue(expression);
+ }
+
+ @Test
+ public void hasJsonPathStringValue() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathStringValue("$.str");
+ }
+
+ @Test
+ public void hasJsonPathStringValueForAnEmptyString() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathStringValue("$.emptyString");
+ }
+
+ @Test
+ public void hasJsonPathStringValueForAnEmptyStringForNonString() throws Exception {
+ String expression = "$.bool";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a string at JSON path \"" + expression + "\" but found: true");
+ assertThat(forJson(TYPES)).hasJsonPathStringValue(expression);
+ }
+
+ @Test
+ public void hasJsonPathNumberValue() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathNumberValue("$.num");
+ }
+
+ @Test
+ public void hasJsonPathNumberValueForNonNumber() throws Exception {
+ String expression = "$.bool";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a number at JSON path \"" + expression + "\" but found: true");
+ assertThat(forJson(TYPES)).hasJsonPathNumberValue(expression);
+ }
+
+ @Test
+ public void hasJsonPathBooleanValue() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathBooleanValue("$.bool");
+ }
+
+ @Test
+ public void hasJsonPathBooleanValueForNonBoolean() throws Exception {
+ String expression = "$.num";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a boolean at JSON path \"" + expression + "\" but found: 5");
+ assertThat(forJson(TYPES)).hasJsonPathBooleanValue(expression);
+ }
+
+ @Test
+ public void hasJsonPathArrayValue() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathArrayValue("$.arr");
+ }
+
+ @Test
+ public void hasJsonPathArrayValueForAnEmptyArray() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathArrayValue("$.emptyArray");
+ }
+
+ @Test
+ public void hasJsonPathArrayValueForNonArray() throws Exception {
+ String expression = "$.str";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected an array at JSON path \"" + expression + "\" but found: 'foo'");
+ assertThat(forJson(TYPES)).hasJsonPathArrayValue(expression);
+ }
+
+ @Test
+ public void assertValueIsMap() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathMapValue("$.colorMap");
+ }
+
+ @Test
+ public void assertValueIsMapForAnEmptyMap() throws Exception {
+ assertThat(forJson(TYPES)).hasJsonPathMapValue("$.emptyMap");
+ }
+
+ @Test
+ public void assertValueIsMapForNonMap() throws Exception {
+ String expression = "$.str";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a map at JSON path \"" + expression + "\" but found: 'foo'");
+ assertThat(forJson(TYPES)).hasJsonPathMapValue(expression);
+ }
+
+ @Test
+ public void extractingJsonPathValue() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathValue("@.str").isEqualTo("foo");
+ }
+
+ @Test
+ public void extractingJsonPathValueForMissing() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathValue("@.bogus").isNull();
+ }
+
+ @Test
+ public void extractingJsonPathStringValue() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathStringValue("@.str")
+ .isEqualTo("foo");
+ }
+
+ @Test
+ public void extractingJsonPathStringValueForMissing() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathStringValue("@.bogus").isNull();
+ }
+
+ @Test
+ public void extractingJsonPathStringValueForEmptyString() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathStringValue("@.emptyString")
+ .isEmpty();
+ }
+
+ @Test
+ public void extractingJsonPathStringValueForWrongType() throws Exception {
+ String expression = "$.num";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a string at JSON path \"" + expression + "\" but found: 5");
+ assertThat(forJson(TYPES)).extractingJsonPathStringValue(expression);
+ }
+
+ @Test
+ public void extractingJsonPathNumberValue() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathNumberValue("@.num").isEqualTo(5);
+ }
+
+ @Test
+ public void extractingJsonPathNumberValueForMissing() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathNumberValue("@.bogus").isNull();
+ }
+
+ @Test
+ public void extractingJsonPathNumberValueForWrongType() throws Exception {
+ String expression = "$.str";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a number at JSON path \"" + expression + "\" but found: 'foo'");
+ assertThat(forJson(TYPES)).extractingJsonPathNumberValue(expression);
+ }
+
+ @Test
+ public void extractingJsonPathBooleanValue() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathBooleanValue("@.bool").isTrue();
+ }
+
+ @Test
+ public void extractingJsonPathBooleanValueForMissing() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathBooleanValue("@.bogus").isNull();
+ }
+
+ @Test
+ public void extractingJsonPathBooleanValueForWrongType() throws Exception {
+ String expression = "$.str";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage("Expected a boolean at JSON path \"" + expression
+ + "\" but found: 'foo'");
+ assertThat(forJson(TYPES)).extractingJsonPathBooleanValue(expression);
+ }
+
+ @Test
+ public void extractingJsonPathArrayValue() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathArrayValue("@.arr")
+ .containsExactly(42);
+ }
+
+ @Test
+ public void extractingJsonPathArrayValueForMissing() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathArrayValue("@.bogus").isNull();
+ }
+
+ @Test
+ public void extractingJsonPathArrayValueForEmpty() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathArrayValue("@.emptyArray").isEmpty();
+ }
+
+ @Test
+ public void extractingJsonPathArrayValueForWrongType() throws Exception {
+ String expression = "$.str";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected an array at JSON path \"" + expression + "\" but found: 'foo'");
+ assertThat(forJson(TYPES)).extractingJsonPathArrayValue(expression);
+ }
+
+ @Test
+ public void extractingJsonPathMapValue() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathMapValue("@.colorMap")
+ .containsEntry("red", "rojo");
+ }
+
+ @Test
+ public void extractingJsonPathMapValueForMissing() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathMapValue("@.bogus").isNull();
+ }
+
+ @Test
+ public void extractingJsonPathMapValueForEmpty() throws Exception {
+ assertThat(forJson(TYPES)).extractingJsonPathMapValue("@.emptyMap").isEmpty();
+ }
+
+ @Test
+ public void extractingJsonPathMapValueForWrongType() throws Exception {
+ String expression = "$.str";
+ this.thrown.expect(AssertionError.class);
+ this.thrown.expectMessage(
+ "Expected a map at JSON path \"" + expression + "\" but found: 'foo'");
+ assertThat(forJson(TYPES)).extractingJsonPathMapValue(expression);
+ }
+
+ @Test
+ public void isNullWhenActualIsNullShouldPass() throws Exception {
+ assertThat(forJson(null)).isNull();
+ }
+
+ private File createFile(String content) throws IOException {
+ File file = this.tempFolder.newFile("file.json");
+ FileCopyUtils.copy(content.getBytes(), file);
+ return file;
+ }
+
+ private InputStream createInputStream(String content) throws IOException {
+ return new ByteArrayInputStream(content.getBytes());
+ }
+
+ private Resource createResource(String content) throws IOException {
+ return new ByteArrayResource(content.getBytes());
+ }
+
+ private static String loadJson(String path) {
+ try {
+ ClassPathResource resource = new ClassPathResource(path,
+ JsonContentAssert.class);
+ return new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+
+ }
+
+ private AssertProvider forJson(final String json) {
+ return new AssertProvider() {
+
+ @Override
+ public JsonContentAssert assertThat() {
+ return new JsonContentAssert(JsonContentAssertTests.class, json);
+ }
+
+ };
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/JsonContentTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JsonContentTests.java
new file mode 100644
index 0000000000..f1e8913cff
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/JsonContentTests.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.core.ResolvableType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link JsonContent}.
+ *
+ * @author Phillip Webb
+ */
+public class JsonContentTests {
+
+ private static final String JSON = "{\"name\":\"spring\", \"age\":100}";
+
+ private static final ResolvableType TYPE = ResolvableType
+ .forClass(ExampleObject.class);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void createWhenResourceLoadClassIsNullShouldThrowException() throws Exception {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("ResourceLoadClass must not be null");
+ new JsonContent(null, TYPE, JSON);
+ }
+
+ @Test
+ public void createThenJsonIsNullShouldThrowException() throws Exception {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("JSON must not be null");
+ new JsonContent(getClass(), TYPE, null);
+ }
+
+ @Test
+ public void createWhenTypeIsNullShouldCreateContent() throws Exception {
+ JsonContent content = new JsonContent(getClass(),
+ null, JSON);
+ assertThat(content).isNotNull();
+ }
+
+ @Test
+ public void assertThatShouldReturnJsonContentAssert() throws Exception {
+ JsonContent content = new JsonContent(getClass(),
+ TYPE, JSON);
+ assertThat(content.assertThat()).isInstanceOf(JsonContentAssert.class);
+ }
+
+ @Test
+ public void getJsonShouldReturnJson() throws Exception {
+ JsonContent content = new JsonContent(getClass(),
+ TYPE, JSON);
+ assertThat(content.getJson()).isEqualTo(JSON);
+
+ }
+
+ @Test
+ public void toStringWhenHasTypeShouldReturnString() throws Exception {
+ JsonContent content = new JsonContent(getClass(),
+ TYPE, JSON);
+ assertThat(content.toString())
+ .isEqualTo("JsonContent " + JSON + " created from " + TYPE);
+ }
+
+ @Test
+ public void toStringWhenNoTypeShouldReturnString() throws Exception {
+ JsonContent content = new JsonContent(getClass(),
+ null, JSON);
+ assertThat(content.toString()).isEqualTo("JsonContent " + JSON);
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/ObjectContentAssertTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/ObjectContentAssertTests.java
new file mode 100644
index 0000000000..a6b705ee43
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/ObjectContentAssertTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.assertj.core.api.AssertProvider;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ObjectContentAssert}.
+ *
+ * @author Phillip Webb
+ */
+public class ObjectContentAssertTests {
+
+ private static final ExampleObject SOURCE = new ExampleObject();
+
+ private static final ExampleObject DIFFERENT;
+
+ static {
+ DIFFERENT = new ExampleObject();
+ DIFFERENT.setAge(123);
+ }
+
+ @Test
+ public void isEqualToWhenObjectsAreEqualShouldPass() throws Exception {
+ assertThat(forObject(SOURCE)).isEqualTo(SOURCE);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void isEqualToWhenObjectsAreDifferentShouldFail() throws Exception {
+ assertThat(forObject(SOURCE)).isEqualTo(DIFFERENT);
+ }
+
+ @Test
+ public void asArrayForArrayShouldReturnObjectArrayAssert() throws Exception {
+ ExampleObject[] source = new ExampleObject[] { SOURCE };
+ assertThat(forObject(source)).asArray().containsExactly(SOURCE);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void asArrayForNonArrayShouldFail() throws Exception {
+ assertThat(forObject(SOURCE)).asArray();
+ }
+
+ @Test
+ public void asMapForMapShouldReturnMapAssert() throws Exception {
+ Map source = Collections.singletonMap("a", SOURCE);
+ assertThat(forObject(source)).asMap().containsEntry("a", SOURCE);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void asMapForNonMapShouldFail() throws Exception {
+ assertThat(forObject(SOURCE)).asMap();
+ }
+
+ private AssertProvider> forObject(final Object source) {
+ return new AssertProvider>() {
+
+ @Override
+ public ObjectContentAssert assertThat() {
+ return new ObjectContentAssert(source);
+ }
+
+ };
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/json/ObjectContentTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/json/ObjectContentTests.java
new file mode 100644
index 0000000000..55ad734980
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/json/ObjectContentTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-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.springframework.boot.test.json;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.core.ResolvableType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ObjectContent}.
+ *
+ * @author Phillip Webb
+ */
+public class ObjectContentTests {
+
+ private static final ExampleObject OBJECT = new ExampleObject();
+
+ private static final ResolvableType TYPE = ResolvableType
+ .forClass(ExampleObject.class);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void createWhenObjectIsNullShouldThrowException() throws Exception {
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Object must not be null");
+ new ObjectContent(TYPE, null);
+ }
+
+ @Test
+ public void createWhenTypeIsNullShouldCreateContent() throws Exception {
+ ObjectContent content = new ObjectContent(null,
+ OBJECT);
+ assertThat(content).isNotNull();
+ }
+
+ @Test
+ public void assertThatShouldReturnObjectContentAssert() throws Exception {
+ ObjectContent content = new ObjectContent(TYPE,
+ OBJECT);
+ assertThat(content.assertThat()).isInstanceOf(ObjectContentAssert.class);
+ }
+
+ @Test
+ public void getObjectShouldReturnObject() throws Exception {
+ ObjectContent content = new ObjectContent(TYPE,
+ OBJECT);
+ assertThat(content.getObject()).isEqualTo(OBJECT);
+ }
+
+ @Test
+ public void toStringWhenHasTypeShouldReturnString() throws Exception {
+ ObjectContent content = new ObjectContent(TYPE,
+ OBJECT);
+ assertThat(content.toString())
+ .isEqualTo("ObjectContent " + OBJECT + " created from " + TYPE);
+ }
+
+ @Test
+ public void toStringWhenHasNoTypeShouldReturnString() throws Exception {
+ ObjectContent content = new ObjectContent(null,
+ OBJECT);
+ assertThat(content.toString()).isEqualTo("ObjectContent " + OBJECT);
+ }
+
+}
diff --git a/spring-boot-test/src/test/resources/org/springframework/boot/test/json/different.json b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/different.json
new file mode 100644
index 0000000000..99d65c7c17
--- /dev/null
+++ b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/different.json
@@ -0,0 +1,6 @@
+{
+ "gnirps":[
+ "boot",
+ "framework"
+ ]
+}
diff --git a/spring-boot-test/src/test/resources/org/springframework/boot/test/json/example.json b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/example.json
new file mode 100644
index 0000000000..cdea9c3598
--- /dev/null
+++ b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/example.json
@@ -0,0 +1,4 @@
+{
+ "name" : "Spring",
+ "age" : 123
+}
diff --git a/spring-boot-test/src/test/resources/org/springframework/boot/test/json/lenient-same.json b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/lenient-same.json
new file mode 100644
index 0000000000..231865936a
--- /dev/null
+++ b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/lenient-same.json
@@ -0,0 +1,6 @@
+{
+ "spring":[
+ "framework",
+ "boot"
+ ]
+}
diff --git a/spring-boot-test/src/test/resources/org/springframework/boot/test/json/simpsons.json b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/simpsons.json
new file mode 100644
index 0000000000..7e9aad3590
--- /dev/null
+++ b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/simpsons.json
@@ -0,0 +1,19 @@
+{
+ "familyMembers":[
+ {
+ "name":"Homer"
+ },
+ {
+ "name":"Marge"
+ },
+ {
+ "name":"Bart"
+ },
+ {
+ "name":"Lisa"
+ },
+ {
+ "name":"Maggie"
+ }
+ ]
+}
diff --git a/spring-boot-test/src/test/resources/org/springframework/boot/test/json/source.json b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/source.json
new file mode 100644
index 0000000000..93e7f4a96f
--- /dev/null
+++ b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/source.json
@@ -0,0 +1,6 @@
+{
+ "spring":[
+ "boot",
+ "framework"
+ ]
+}
diff --git a/spring-boot-test/src/test/resources/org/springframework/boot/test/json/types.json b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/types.json
new file mode 100644
index 0000000000..c418206984
--- /dev/null
+++ b/spring-boot-test/src/test/resources/org/springframework/boot/test/json/types.json
@@ -0,0 +1,19 @@
+{
+ "str":"foo",
+ "num":5,
+ "bool":true,
+ "arr":[
+ 42
+ ],
+ "colorMap":{
+ "red":"rojo"
+ },
+ "whitespace":" ",
+ "emptyString":"",
+ "emptyArray":[
+
+ ],
+ "emptyMap":{
+
+ }
+}