2015-12-05 13 views
7

sto usando le classi Hamcrest CoreMatcher come parte di spring-test test di integrazione. Il mio JSON assomiglia:Hamcrest matcher confrontando valore doppio da JSON

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

E il mio test di integrazione appare come:

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

Tuttavia, l'affermazione fallisce:

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

So che c'è una parte IsCloseTo matcher qui: http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/number/IsCloseTo.html , ma il suo utilizzo in questo modo:

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

produce un errore strano:

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) 

Speravo di evitare di dover includere qualche tipo di errore - io voglio il valore restituito per essere esattamente 4, solo che non mi importa quanti finale gli zeri sono inclusi.

+0

Il problema è che il valore 'double' viene utilizzato per creare l'oggetto del modello che viene poi controllato per come parte di la risposta JSON, quindi speravo di riutilizzare la stessa variabile per evitare di scriverla due volte. Aggiornerò il mio codice per dimostrarlo. –

+0

Stai utilizzando Java 8 a proposito? – Tunaki

+0

Sì, sto usando Java 8. –

risposta

2

Il problema è che la partita viene eseguita su Integer s e non su valori doppi.

Stai correttamente dando una Matcher<Double>. Spring usa Jayway sotto il cofano per analizzare il JSON e il tuo percorso JSON sarà valutato come un oggetto Integer. La corrispondenza fallirà perché uno Integer e uno Double sono sempre diseguali.

Come tale, è necessario modificare il Matcher in is((int) miles).

Se non si controlla la JSON si stanno ottenendo e la distanceInMiles potrebbe cambiare, questo è più problematico. Jayway analizzerà "4" come Integer ma analizzerà "4.0" come Double. In questo caso, si dovrà implementare la propria Matcher che gestisce entrambi i Integer e Double oggetti estendendo TypeSafeMatcher. Questo sarebbe un semplice implementazione:

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

} 

Esso corrisponde a qualsiasi Number confrontando il loro valore doppio ad un doppio valore noto.

+0

Sfortunatamente 'closeTo' mi ha dato alcuni problemi davvero strani - domanda aggiornata. –

+0

@CraigOtis Sì, questo è perché non è ancora il tipo previsto. Ho dimenticato che Hamcrest fa un controllo di tipo. Dovrai implementare il tuo matcher. – Tunaki

+0

Ok, non preoccuparti - grazie! –

1

ho scoperto che per default è confrontare come galleggiante, in modo da provare qualcosa di simile:

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