2015-12-05 40 views
7

我使用Hamcrest CoreMatcher类作为spring-test集成测试的一部分。我的JSON的样子:Hamcrest matcher比较来自JSON的double值

{"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,我不在乎有多少尾随包括零。

+0

的问题是,'double'值用于创建模型对象,然后被检查的一部分JSON响应,所以我希望能重复使用相同的变量来避免输入两次。我会更新我的代码块来演示。 –

+0

您是否正在使用Java 8? – Tunaki

+0

是的,我正在使用Java 8. –

回答

2

的问题是,在匹配上Integer s且不对双值执行。

您正确给Matcher<Double>。 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

+0

不幸的是'closeTo'也给了我一些非常奇怪的问题 - 更新了问题。 –

+0

@CraigOtis是的,这是因为它仍然不是预期的类型。我忘了Hamcrest做了一次类型检查。你将不得不实现你自己的匹配器。 – Tunaki

+0

好的,不用担心 - 谢谢! –

1

我发现,在默认情况下是比较为float,所以你可以试试:

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