2015-12-05 5 views
7

Ich verwende die Hamcrest CoreMatcher Klassen als Teil der spring-test Integrationstests. Meine JSON wie folgt aussieht:Hamcrest Matcher vergleicht doppelten Wert von JSON

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

Und meine Integrationstest wie folgt aussieht:

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

jedoch die Behauptung fehlschlägt:

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

Ich weiß, dass es einen separaten IsCloseTo Matcher hier: http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/number/IsCloseTo.html , aber es so verwendend:

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

Ergebnisse in einem seltsamen Fehler:

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) 

Ich hatte gehofft, eine Art von Fehler zu vermeiden, schließen - ich der zurückgegebene Wert wollen genau 4 sein, ist mir egal einfach nicht, wie viele nachlauf Nullen sind enthalten.

+0

Das Problem ist, dass der 'double' Wert das Modellobjekt erstellen verwendet wird, die für die wird dann als Teil geprüft von die JSON-Antwort, also hoffte ich, die gleiche Variable wiederzuverwenden, um es zweimal zu vermeiden. Ich werde meinen Codeblock aktualisieren, um zu demonstrieren. –

+0

Benutzt du übrigens Java 8? – Tunaki

+0

Ja, ich benutze Java 8. –

Antwort

2

Das Problem ist, dass die Übereinstimmung auf Integer s und nicht auf doppelte Werte durchgeführt wird.

Sie geben richtig eine Matcher<Double>. Spring verwendet Jayway unter der Haube, um den JSON zu analysieren, und Ihr JSON-Pfad wird als Integer-Objekt ausgewertet. Der Abgleich schlägt fehl, da Integer und Double immer ungleich sind.

Als solche müssen Sie Ihre Matcher zu is((int) miles) ändern.

Wenn Sie den JSON, den Sie erhalten, nicht kontrollieren und sich die distanceInMiles ändern kann, ist dies problematischer. Jayway wird "4" als Integer analysieren, aber es wird "4.0" als Double analysieren. In diesem Fall müssen Sie Ihre eigene Matcher implementieren, die sowohl Integer als auch Double Objekte verarbeitet, indem Sie TypeSafeMatcher erweitern. Dies wäre eine einfache Implementierung sein:

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

} 

Sie paßt zu jedem Number durch ihren doppelten Wert auf einen bekannten Doppelwert verglichen wird.

+0

Leider hat 'closeTo' mir einige wirklich seltsame Probleme gegeben - Frage aktualisiert. –

+0

@CraigOtis Ja, weil es immer noch nicht der erwartete Typ ist. Ich habe vergessen, dass Hamcrest eine Typprüfung durchführt. Sie müssen Ihren eigenen Matcher implementieren. – Tunaki

+0

Okay, keine Sorgen - danke! –

1

Ich fand heraus, dass standardmäßig als Schwimmer zu vergleichen, so versuchen, so etwas wie:

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