Skip to content

Commit

Permalink
#218 Allow differentiating between number and integer
Browse files Browse the repository at this point in the history
  • Loading branch information
lukas-krecan-lt committed Feb 29, 2020
1 parent 70c2cc8 commit cff0b93
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.AbstractStringAssert;
import org.assertj.core.api.BigDecimalAssert;
import org.assertj.core.api.BigIntegerAssert;
import org.assertj.core.api.BooleanAssert;
import org.assertj.core.api.ListAssert;
import org.assertj.core.api.MapAssert;
Expand Down Expand Up @@ -155,6 +156,15 @@ public BigDecimalAssert isNumber() {
return createBigDecimalAssert(node.decimalValue());
}

/**
* Asserts that the value is an integer. 1 is an integer 1.0, 1.1, 1e3, 1e0, 1e-3 is not.
*/
public BigIntegerAssert isIntegralNumber() {
Node node = internalMatcher.assertIntegralNumber();
return new BigIntegerAssert(node.decimalValue().toBigIntegerExact())
.as("Different value found in node \"%s\"", path);
}

/**
* Asserts that given node is present and is of type number or a string that can be parsed as a number.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ public BigDecimal decimalValue() {
return jsonNode.getAsBigDecimal();
}

@Override
public boolean isIntegralNumber() {
String string = jsonNode.getAsString();
return jsonNode.getAsBigDecimal().scale() == 0 && !string.contains("e") && !string.contains("E");
}

public Boolean asBoolean() {
return jsonNode.getAsBoolean();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,20 @@ public String asText() {

@Override
public BigDecimal decimalValue() {
if (jsonNode.getValueType() == JsonValue.ValueType.NUMBER)
if (isNumber()) {
return ((JsonNumber) jsonNode).bigDecimalValue();
else
} else {
throw new IllegalStateException("Not a JsonNumber: " + jsonNode);
}
}

@Override
public boolean isIntegralNumber() {
return isNumber() && ((JsonNumber)jsonNode).isIntegral();
}

private boolean isNumber() {
return jsonNode.getValueType() == JsonValue.ValueType.NUMBER;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ public BigDecimal decimalValue() {
return value.scale() < 0 ? value.setScale(0, RoundingMode.HALF_UP) : value;
}

@Override
public boolean isIntegralNumber() {
throw new UnsupportedOperationException("Moshi is not able to tell apart integer and decimal number");
}

@Override
public String toString() {
return decimalValue().toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ public String getDescription() {

BigDecimal decimalValue();

/**
* Returns true if the value is an integer. 1 is an integer 1.0, 1.1, 1e3, 1e0, 1e-3 is not.
*/
default boolean isIntegralNumber() {
BigDecimal decimalValue = decimalValue();
String text = decimalValue.toString();
return decimalValue.scale() == 0 && !text.contains("e") && !text.contains("E");
}

Boolean asBoolean();

Object getValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import static net.javacrumbs.jsonunit.core.internal.JsonUtils.nodeAbsent;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.ARRAY;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.NULL;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.NUMBER;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.OBJECT;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.STRING;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -274,6 +275,15 @@ public Node assertType(@NotNull Node.NodeType type) {
return node;
}

@NotNull
public Node assertIntegralNumber() {
Node node = assertType(NUMBER);
if (!node.isIntegralNumber()) {
failOnType(node, "integer");
}
return node;
}

/**
* Fails if the selected JSON is not an Object or is not present.
*/
Expand Down Expand Up @@ -309,9 +319,12 @@ private void failOnType(@NotNull Node node, @NotNull Node.NodeType expectedType)
}

public void failOnType(@NotNull Node node, @NotNull String expectedType) {
failWithMessage("Node \"" + path + "\" has invalid type, expected: <" + expectedType + "> but was: <" + quoteTextValue(node.getValue()) + ">.");
failOnType(expectedType, quoteTextValue(node.getValue()));
}

private void failOnType(@NotNull String expectedType, @Nullable Object actualType) {
failWithMessage("Node \"" + path + "\" has invalid type, expected: <" + expectedType + "> but was: <" + actualType + ">.");
}

/**
* Matches the node using Hamcrest matcher.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,41 @@ void shouldAssertAsNumber() {
assertThatJson("{\"a\":1}").node("a").asNumber().isEqualByComparingTo("1");
}

@Test
void shouldAssertInteger() {
assertThatJson("{\"a\":1}").node("a").isIntegralNumber().isEqualTo(1);
assertThatJson("{\"a\":10}").node("a").isIntegralNumber();
assertThatJson("{\"a\":0}").node("a").isIntegralNumber();
assertThatJson("{\"a\":-10}").node("a").isIntegralNumber();
}

@Test
void shouldAssertIntegerFailure() {
assertThatThrownBy(() -> assertThatJson("{\"a\":1.0}").node("a").isIntegralNumber())
.hasMessage("Node \"a\" has invalid type, expected: <integer> but was: <1.0>.");

assertThatThrownBy(() -> assertThatJson("{\"a\":0.0}").node("a").isIntegralNumber())
.hasMessage("Node \"a\" has invalid type, expected: <integer> but was: <0.0>.");

assertThatThrownBy(() -> assertThatJson("{\"a\":10.0}").node("a").isIntegralNumber())
.hasMessage("Node \"a\" has invalid type, expected: <integer> but was: <10.0>.");

assertThatThrownBy(() -> assertThatJson("{\"a\":-10.0}").node("a").isIntegralNumber())
.hasMessage("Node \"a\" has invalid type, expected: <integer> but was: <-10.0>.");

assertThatThrownBy(() -> assertThatJson("{\"a\":1.1}").node("a").isIntegralNumber())
.hasMessage("Node \"a\" has invalid type, expected: <integer> but was: <1.1>.");

assertThatThrownBy(() -> assertThatJson("{\"a\":1e3}").node("a").isIntegralNumber())
.hasMessageStartingWith("Node \"a\" has invalid type, expected: <integer> but was:");

assertThatThrownBy(() -> assertThatJson("{\"a\":1e-3}").node("a").isIntegralNumber())
.hasMessage("Node \"a\" has invalid type, expected: <integer> but was: <0.001>.");

assertThatThrownBy(() -> assertThatJson("{\"a\":1e0}").node("a").isIntegralNumber())
.hasMessageStartingWith("Node \"a\" has invalid type, expected: <integer> but was:");
}

@Test
void shouldAssertStringNumber() {
assertThatJson("{\"a\":\"1\"}").node("a").asNumber().isEqualByComparingTo("1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,28 @@
package net.javacrumbs.jsonunit.test.moshi;

import net.javacrumbs.jsonunit.test.base.AbstractAssertJTest;
import org.junit.jupiter.api.Test;

import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static net.javacrumbs.jsonunit.test.base.JsonTestUtils.readByMoshi;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class MoshiAssertJTest extends AbstractAssertJTest {

@Override
protected Object readValue(String value) {
return readByMoshi(value);
}

@Test
void shouldAssertInteger() {
assertThatThrownBy(() ->assertThatJson("{\"a\":1}").node("a").isIntegralNumber())
.isInstanceOf(UnsupportedOperationException.class);
}

@Test
void shouldAssertIntegerFailure() {
assertThatThrownBy(() -> assertThatJson("{\"a\":1.0}").node("a").isIntegralNumber())
.isInstanceOf(UnsupportedOperationException.class);
}
}

0 comments on commit cff0b93

Please sign in to comment.