All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.javacrumbs.jsonunit.fluent.JsonFluentAssert Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
/**
 * Copyright 2009-2019 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 net.javacrumbs.jsonunit.fluent;

import static net.javacrumbs.jsonunit.core.internal.JsonUtils.convertToJson;
import static net.javacrumbs.jsonunit.core.internal.JsonUtils.getPathPrefix;
import static net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher.ACTUAL;

import java.math.BigDecimal;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.ConfigurationWhen;
import net.javacrumbs.jsonunit.core.ConfigurationWhen.ApplicableForPath;
import net.javacrumbs.jsonunit.core.ConfigurationWhen.PathsParam;
import net.javacrumbs.jsonunit.core.Option;
import net.javacrumbs.jsonunit.core.internal.Path;
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
import net.javacrumbs.jsonunit.core.listener.DifferenceListener;
import org.hamcrest.Matcher;

/**
 * Contains JSON related fluent assertions inspired by FEST or AssertJ. Typical usage is:
 *
 * 
 * assertThatJson("{\"test\":1}").isEqualTo("{\"test\":2}");
 * assertThatJson("{\"test\":1}").hasSameStructureAs("{\"test\":21}");
 * assertThatJson("{\"root\":{\"test\":1}}").node("root.test").isEqualTo("2");
 * 
 *
 * Please note that the method name is assertThatJson and not assertThat. The reason is that we need to accept String parameter
 * and do not want to override standard FEST or AssertJ assertThat(String) method.
 *
 * All the methods accept Objects as parameters. The supported types are:
 * 
    *
  1. Jackson JsonNode
  2. *
  3. Gson JsonElement
  4. *
  5. Numbers, booleans and any other type parsable by underlying JSON library
  6. *
  7. String is parsed as JSON. For expected values the string is quoted if it contains obviously invalid JSON.
  8. *
  9. {@link java.io.Reader} similarly to String
  10. *
  11. null as null Node
  12. *
*/ public class JsonFluentAssert { final InternalMatcher internalMatcher; private JsonFluentAssert(InternalMatcher internalMatcher) { this.internalMatcher = internalMatcher; } private JsonFluentAssert(Object actual, Path path, String description, Configuration configuration) { this.internalMatcher = new InternalMatcher(actual, path, description, configuration); } private JsonFluentAssert(Object actual, String pathPrefix) { this(actual, Path.create("", pathPrefix), "", Configuration.empty()); } /** * Creates a new instance of {@link JsonFluentAssert}. * It is not called assertThat to not clash with StringAssert. * The json parameter is converted to JSON using ObjectMapper. * * @param json * @return new JsonFluentAssert object. */ public static ConfigurableJsonFluentAssert assertThatJson(Object json) { return new ConfigurableJsonFluentAssert(convertToJson(json, ACTUAL), getPathPrefix(json)); } /** * Compares JSON for equality. The expected object is converted to JSON * before comparison. Ignores order of sibling nodes and whitespaces. * * Please note that if you pass a String, it's parsed as JSON which can lead to an * unexpected behavior. If you pass in "1" it is parsed as a JSON containing * integer 1. If you compare it with a string it fails due to a different type. * If you want to pass in real string you have to quote it "\"1\"" or use * {@link #isStringEqualTo(String)}. * * If the string parameter is not a valid JSON, it is quoted automatically. * * @param expected * @return {@code this} object. * @see #isStringEqualTo(String) */ public JsonFluentAssert isEqualTo(Object expected) { internalMatcher.isEqualTo(expected); return this; } /** * Fails if the selected JSON is not a String or is not present or the value * is not equal to expected value. */ public JsonFluentAssert isStringEqualTo(String expected) { internalMatcher.isStringEqualTo(expected); return this; } /** * Fails if compared documents are equal. The expected object is converted to JSON * before comparison. Ignores order of sibling nodes and whitespaces. * * @param expected * @return {@code this} object. */ public JsonFluentAssert isNotEqualTo(Object expected) { internalMatcher.isNotEqualTo(expected); return this; } /** * Creates an assert object that only compares given node. * The path is denoted by JSON path, for example. * * * assertThatJson("{\"root\":{\"test\":[1,2,3]}}").node("root.test[0]").isEqualTo("1"); * * * @param newPath * @return object comparing only node given by path. */ public JsonFluentAssert node(String newPath) { return new JsonFluentAssert(internalMatcher.node(newPath)); } /** * Fails if the node exists. * * @return */ public JsonFluentAssert isAbsent() { internalMatcher.isAbsent(); return this; } /** * Fails if the node is missing. */ public JsonFluentAssert isPresent() { internalMatcher.isPresent(); return this; } /** * Fails if the selected JSON is not an Array or is not present. * * @return */ public ArrayAssert isArray() { return new ArrayAssert(internalMatcher.isArray()); } /** * Fails if the selected JSON is not an Object or is not present. */ public void isObject() { internalMatcher.isObject(); } /** * Fails if the selected JSON is not a String or is not present. */ public void isString() { internalMatcher.isString(); } /** * Matches the node using Hamcrest internalMatcher. * *
    *
  • Numbers are mapped to BigDecimal
  • *
  • Arrays are mapped to a Collection
  • *
  • Objects are mapped to a map so you can use json(Part)Equals or a Map internalMatcher
  • *
* * @param matcher * @return */ public JsonFluentAssert matches(Matcher matcher) { internalMatcher.matches(matcher); return this; } /** * Array assertions */ public static class ArrayAssert { private final InternalMatcher.ArrayMatcher arrayMatcher; ArrayAssert(InternalMatcher.ArrayMatcher arrayMatcher) { this.arrayMatcher = arrayMatcher; } /** * Fails if the array has different length. * @param expectedLength * @return */ public ArrayAssert ofLength(int expectedLength) { arrayMatcher.ofLength(expectedLength); return this; } public ArrayAssert thatContains(Object expected) { arrayMatcher.thatContains(expected); return this; } public ArrayAssert isEmpty() { arrayMatcher.isEmpty(); return this; } public ArrayAssert isNotEmpty() { arrayMatcher.isNotEmpty(); return this; } } /** * JsonFluentAssert that can be configured. To make sure that configuration is done before comparison and not after. */ public static class ConfigurableJsonFluentAssert extends JsonFluentAssert { private ConfigurableJsonFluentAssert(InternalMatcher internalMatcher) { super(internalMatcher); } private ConfigurableJsonFluentAssert(Object actual, String pathPrefix) { super(actual, pathPrefix); } /** * Creates an assert object that only compares given node. * The path is denoted by JSON path, for example. Second call navigates from the root. * * * assertThatJson("{\"root\":{\"test\":[1,2,3]}}").node("root.test[0]").isEqualTo("1"); * * * @param newPath * @return object comparing only node given by path. */ @Override public ConfigurableJsonFluentAssert node(String newPath) { return new ConfigurableJsonFluentAssert(internalMatcher.node(newPath)); } /** * Makes JsonUnit ignore the specified paths in the actual value. If the path matches, * it's completely ignored. It may be missing, null or have any value */ public ConfigurableJsonFluentAssert whenIgnoringPaths(String... pathsToBeIgnored) { return new ConfigurableJsonFluentAssert(internalMatcher.whenIgnoringPaths(pathsToBeIgnored)); } /** * Sets the description of this object. * * @param description * @return */ public ConfigurableJsonFluentAssert as(String description) { return describedAs(description); } /** * Sets the description of this object. * * @param description * @return */ public ConfigurableJsonFluentAssert describedAs(String description) { return new ConfigurableJsonFluentAssert(internalMatcher.describedAs(description)); } /** * Sets the placeholder that can be used to ignore values. * The default value is ${json-unit.ignore} * * @param ignorePlaceholder * @return */ public ConfigurableJsonFluentAssert ignoring(String ignorePlaceholder) { return new ConfigurableJsonFluentAssert(internalMatcher.withIgnorePlaceholder(ignorePlaceholder)); } /** * Sets the tolerance for floating number comparison. If set to null, requires exact match of the values. * For example, if set to 0.01, ignores all differences lower than 0.01, so 1 and 0.9999 are considered equal. * * @param tolerance */ public ConfigurableJsonFluentAssert withTolerance(double tolerance) { return new ConfigurableJsonFluentAssert(internalMatcher.withTolerance(tolerance)); } /** * Sets the tolerance for floating number comparison. If set to null, requires exact match of the values. * For example, if set to 0.01, ignores all differences lower than 0.01, so 1 and 0.9999 are considered equal. * * @param tolerance */ public ConfigurableJsonFluentAssert withTolerance(BigDecimal tolerance) { return new ConfigurableJsonFluentAssert(internalMatcher.withTolerance(tolerance)); } /** * Adds a internalMatcher to be used in ${json-unit.matches:matcherName} macro. */ public ConfigurableJsonFluentAssert withMatcher(String matcherName, Matcher matcher) { return new ConfigurableJsonFluentAssert(internalMatcher.withMatcher(matcherName, matcher)); } public ConfigurableJsonFluentAssert withDifferenceListener(DifferenceListener differenceListener) { return new ConfigurableJsonFluentAssert(internalMatcher.withDifferenceListener(differenceListener)); } /** * Sets options changing comparison behavior. This method has to be called * before assertion. * For more info see {@link net.javacrumbs.jsonunit.core.Option} * * @param firstOption * @param otherOptions * @see net.javacrumbs.jsonunit.core.Option */ public ConfigurableJsonFluentAssert when(Option firstOption, Option... otherOptions) { return new ConfigurableJsonFluentAssert(internalMatcher.withOptions(firstOption, otherOptions)); } /** * Sets advanced/local options. This method has to be called before assertion. * For more information see {@link Configuration#when(PathsParam, ApplicableForPath...)} * * @see Configuration#when(ConfigurationWhen.PathsParam, ApplicableForPath...) */ public final ConfigurableJsonFluentAssert when(PathsParam object, ApplicableForPath... actions) { return new ConfigurableJsonFluentAssert(internalMatcher.when(object, actions)); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy