Hamcrest matcher comparing double value from JSON

I'm using the Hamcrest CoreMatcher classes as part of spring-test integration tests. My JSON looks like:

{"data":[{"distanceInMiles":4,"id":"f97236ba-f4ef-4...

And my integration test looks like:

double miles = 4.0
Activity a = new BasicActivity(miles);
this.activityManager.add(a); // A mock activity manager (in-memory)
...
this.mockMvc.perform(get("/").accept("application/json"))
    .andExpect(jsonPath("$.data[0].distanceInMiles", is(miles)))

However, the assertion fails:

java.lang.AssertionError: JSON path "$.data[0].distanceInMiles"
Expected: is <4.0>
     but: was <4>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)

I know that there's a separate IsCloseTo matcher here: http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/number/IsCloseTo.html, but using it like so:

.andExpect(jsonPath("$.data[0].distanceInMiles", closeTo(miles, 0)))

results in a strange error:

java.lang.AssertionError: JSON path "$.data[0].distanceInMiles"
Expected: a numeric value within <0.0> of <4.0>
     but: was a java.lang.Integer (<4>)
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)

I was hoping to avoid having to include some kind of error - I want the returned value to be exactly 4 , I just don't care how many trailing zeroes are included.


The problem is that the match is performed on Integer s and not on double values.

You are correctly giving a Matcher<Double> . Spring uses Jayway under the hood for parsing the JSON and your JSON path will be evaluated as an Integer object. The matching will fail because an Integer and a Double are always unequal.

As such, you need to change your Matcher to is((int) miles) .

If you don't control the JSON you are getting and the distanceInMiles might change, this is more problematic. Jayway will parse "4" as an Integer but it will parse "4.0" as a Double . In this case, you will have to implement your own Matcher that handles both Integer and Double objects by extending TypeSafeMatcher . This would be a simple implementation:

class NumberMatcher extends TypeSafeMatcher<Number> {

    private double value;

    public NumberMatcher(double value) {
        this.value = value;
    }

    @Override
    public void describeTo(Description description) {
        // some description
    }

    @Override
    protected boolean matchesSafely(Number item) {
        return item.doubleValue() == value;
    }

}

It matches any Number by comparing their double value to a known double value.


我发现默认情况下比较为float,所以请尝试如下所示:

.body("field_with_double_value",is(100.0f));
链接地址: http://www.djcxy.com/p/30772.html

上一篇: C ++ 11如何观察atomic :: store和atomic :: load中的内存顺序

下一篇: 比较来自JSON的double值的Hamcrest匹配器