2016-04-12 26 views
9

Sto scrivendo dei test per verificare che posso inviare un modulo generico alla nostra API.Test dei messaggi di modulo tramite MockMVC

Ho anche aggiunto un po 'di debug, ma ho notato che i dati inviati da un modulo effettivo; (Postman/AngularJS o w/e) si differenzia dal fare un test mockMVC come:

MvcResult response = mockMvc 
      .perform(post("/some/super/secret/url") // 
        .param("someparam1", "somevalue") // 
        .param("someparam2", "somevalue") //     
        .contentType(MediaType.APPLICATION_FORM_URLENCODED) // 
        .accept(MediaType.APPLICATION_JSON)) // 
      .andExpect(status().isOk()) // 
      .andReturn(); 

La configurazione è esattamente la stessa della configurazione in esecuzione in produzione, e così via. Tuttavia quando la mia intercettore registra il contenuto, nella prova reale (non mockMVC) il contenuto è formattato come "someparam1 = someValue & ecc = bis"

Quando stampo il contenuto mockMVC Io in realtà sembrano non avere alcun contenuto, ma ci sono Param nella richiesta, presumo siano aggiunti come parametri GET.

Qualcuno sa come testare correttamente questo? Mi sono imbattuto in questo problema poiché sembra che i nostri post non sembrino essere analizzati da Spring anche se abbiamo il FormHttpMessageConverter aggiunto al contesto servlet.

+0

Puoi fornire maggiori dettagli, come la configurazione, dati reali si registra al server e qualche dettaglio di log per renderlo più chiaro? Per quanto riguarda la simulazione, sembra che tu stia facendo bene, il parametro del test di simulazione è lo stesso tipo di formato dei dati dei post che mostri. Inoltre, controlla se hai qualche pensiero come sicurezza di primavera. Potrebbe essere necessario prendere in giro la sicurezza di primavera o eseguire il login prima di fare i passi successivi. –

+1

Non usiamo nulla del genere, quello che ho scoperto è che il mio esempio è in realtà sbagliato. in questo caso someParam1 e someParam2 saranno una query param, (In url). Voglio usare i parametri del modulo quindi URLENCODED. Questo tuttavia sembra essere accessibile solo attraverso un modello o una mappa di valori. Quindi avremo bisogno di una soluzione alternativa (questo è stato migrato per essere completamente mvc di primavera, usato per essere @FormParam che non è primavera). –

+0

Oh anche i dati inviati, erano come nel mio esempio sotto la parte Mvc, sta pubblicando una stringa di contenuti concatenata con & e = –

risposta

10

Se avete Apache HTTPComponents HttpClient sul classpath, si può fare in questo modo:

mockMvc.perform(post("/some/super/secret/url") 
      .contentType(MediaType.APPLICATION_FORM_URLENCODED) 
      .content(EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
        new BasicNameValuePair("someparam1", "true"), 
        new BasicNameValuePair("someparam2", "test") 
      ))))); 

Se non si dispone di HttpClient, lo si può fare con un semplice metodo di supporto che costruisce la forma urlencoded entità:

mockMvc.perform(post("/some/super/secret/url") 
      .contentType(MediaType.APPLICATION_FORM_URLENCODED) 
      .content(buildUrlEncodedFormEntity(
     "someparam1", "value1", 
     "someparam2", "value2" 
    )))); 

Con questa funzione di supporto:

String buildUrlEncodedFormEntity(String... params) { 
    if((params.length%2)>0) { 
     throw new IllegalArgumentException("Need to give an even number of parameters"); 
    } 
    StringBuilder result = new StringBuilder(); 
    for(int i=0; i<params.length; i+=2) { 
     if(i>0) result.append('&'); 
     result.append(URLEncoder.encode(params[i]) 
      .append('=') 
      .append(URLEncoder.encode(params[i+1]); 
    } 
    return result.toString(); 
} 
+0

Non è il massimo, ma è una soluzione. Puoi dirmi perché hai bisogno di Apache HTTPComponents?Per quanto posso vedere, questo è realizzabile senza librerie aggiuntive. Per ora come unica risposta accetterò questo, sembra che sia difficile da testare in MockMVC –

+1

Perché pensi che la mia soluzione non sia buona? Non hai bisogno di HTTPComponents, l'ho appena usato perché lo avevo comunque sul classpath. È possibile utilizzare qualsiasi libreria in grado di costruire un'entità modulo codificata URL, che non è altro che "urlencode ('name1') + '=' + urlencode (value1) + '&' + ...'. Potresti scrivere il tuo metodo di supporto per costruirlo –

+0

Penso che volevo dire che sarebbe stato più bello se ci fosse un'implementazione in mockMVC, questo funziona e va bene, ma rimane una soluzione alternativa. Divertente Vedo che ho risposto dopo che non ho lavorato con Java per un po ' –

1

È Coul d utilizzare anche questa piccola libreria che ho creato: https://github.com/f-lopes/spring-mvc-test-utils/.

Aggiungi dipendenza in pom.xml:

<dependency> 
    <groupId>io.florianlopes</groupId> 
    <artifactId>spring-mvc-test-utils</artifactId> 
    <version>1.0.1</version> 
    <scope>test</scope> 
</dependency> 

utilizzarlo con MockMvc:

mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users", new AddUserForm("John", "Doe", null, new Address(1, "Street", 5222, "New York")))) 
    .andExpect(MockMvcResultMatchers.status().isFound()) 
    .andExpect(MockMvcResultMatchers.redirectedUrl("/users")) 
    .andExpect(MockMvcResultMatchers.flash().attribute("message", "success")); 

Questa libreria aggiunge semplicemente i parametri per la richiesta MockMvc, secondo l'oggetto modulo.

Ecco un tutorial dettagliato che ho scritto: https://blog.florianlopes.io/tool-for-spring-mockmvcrequestbuilder-forms-tests/

+2

Si consiglia di leggere [Come offrire librerie open source personali?] (// meta.stackexchange.com/q/229085) –