Hamcrest匹配器比较JSON的双值

Cra*_*tis 7 java spring json hamcrest spring-test

我正在使用Hamcrest CoreMatcher类作为spring-test集成测试的一部分.我的JSON看起来像:

{"data":[{"distanceInMiles":4,"id":"f97236ba-f4ef-4...
Run Code Online (Sandbox Code Playgroud)

我的集成测试看起来像:

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)))
Run Code Online (Sandbox Code Playgroud)

但是,断言失败了:

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

我知道这里有一个单独的IsCloseTo匹配器:http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/number/IsCloseTo.html,但是像这样使用它:

.andExpect(jsonPath("$.data[0].distanceInMiles", closeTo(miles, 0)))
Run Code Online (Sandbox Code Playgroud)

导致一个奇怪的错误:

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)
Run Code Online (Sandbox Code Playgroud)

我希望避免包含某种错误 - 我希望返回的值完全正确4,我只是不关心包含多少尾随零.

Tun*_*aki 4

问题是匹配是在Integers 上执行的,而不是在 double 值上执行的。

您正确地给出了Matcher<Double>. Spring 在底层使用 Jayway 来解析 JSON,并且您的 JSON 路径将被评估为一个Integer对象。匹配会失败,因为 anInteger和 aDouble总是不相等。

因此,您需要将您的更改Matcher为is((int) miles).

如果您不控制所获取的 JSON 并且它distanceInMiles可能会发生变化,那么问题会更大。Jayway 将解析"4"为 anInteger但它会解析"4.0"为Double. 在这种情况下,您必须通过扩展 来实现自己的Matcher处理Integer和Double对象TypeSafeMatcher。这将是一个简单的实现:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

它Number通过将双精度值与已知的双精度值进行比较来匹配任何一个。