【问题标题】:Hamcrest matcher comparing double value from JSONHamcrest 匹配器比较来自 JSON 的双精度值
【发布时间】:2015-12-05 15:51:01
【问题描述】:

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

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

我的集成测试看起来像:

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)))

但是,断言失败:

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

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

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

导致一个奇怪的错误:

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)

我希望避免包含某种错误 - 我希望返回的值正好是 4,我只是不在乎包含多少尾随零。 p>

【问题讨论】:

  • 问题是 double 值用于创建模型对象,然后将其作为 JSON 响应的一部分进行检查,因此我希望重用相同的变量以避免输入两次.我将更新我的代码块以进行演示。
  • 顺便说一句,您使用的是 Java 8 吗?
  • 是的,我使用的是 Java 8。

标签: java json spring spring-test hamcrest


【解决方案1】:

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

您正确地给出了Matcher&lt;Double&gt;。 Spring 在后台使用 Jayway 解析 JSON,您的 JSON 路径将被评估为 Integer 对象。匹配将失败,因为 IntegerDouble 始终不相等。

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

如果你不控制你得到的 JSON 并且 distanceInMiles 可能会改变,这会更成问题。 Jayway 会将"4" 解析为Integer,但会将"4.0" 解析为Double。在这种情况下,您必须实现自己的Matcher,通过扩展TypeSafeMatcher 来处理IntegerDouble 对象。这将是一个简单的实现:

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

}

通过将 Number 的 double 值与已知的 double 值进行比较来匹配任何 Number

【讨论】:

  • 不幸的是 closeTo 也给了我一些非常奇怪的问题 - 问题已更新。
  • @CraigOtis 是的,这是因为它仍然不是预期的类型。我忘记了 Hamcrest 会进行类型检查。您必须实现自己的匹配器。
【解决方案2】:

我发现默认情况下比较为浮点数,所以尝试类似:

.body("field_with_double_value",is(100.0f));

【讨论】:

  • 以及如何使用双精度而不是浮点数进行这种比较?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
  • 2020-12-02
  • 2015-12-26
  • 2015-12-17
  • 1970-01-01
相关资源
最近更新 更多