2016-04-12 13 views
9

Ich schreibe Tests, um zu überprüfen, dass ich eine generische Form Post zu unserer API machen kann.Testformular Beiträge über MockMVC

Ich habe auch einiges Debugging hinzugefügt, aber ich habe festgestellt, dass die Daten von einem tatsächlichen Formular gepostet wurden; (Postman/AngularJS oder w/e) unterscheidet sich von einem mockMVC Test tun wie:

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

Die Config ist genau die gleiche wie die Konfiguration in der Produktion läuft, und so. Jedoch Wenn mein Abfangjäger den Inhalt in Echt Prüfprotokolle (nicht mockMVC) wird der Inhalt formatiert wie „someparam1 = somevalue & etc = Zugabe“

Wenn ich den mockMVC Inhalt drucken tatsächlich scheine ich keinen Inhalt zu haben, aber es gibt Params in der Anfrage, ich nehme an, dass sie wie GET-Parameter hinzugefügt werden.

Wer weiß, wie man das richtig testet? Ich bin auf dieses Problem gestoßen, da es so aussieht, als ob unsere Formular-Posts nicht von Spring geparst werden, obwohl wir den FormHttpMessageConverter zum Servlet-Kontext hinzugefügt haben.

+0

Können Sie mehr Details liefern, wie die Konfiguration, reale Daten, die Sie auf den Server und einige Protokolle Detail schreiben, um es klar? Über den Schein, es scheint, dass Sie Recht haben, der Param des Scheintests ist die gleiche Art von Format von Post-Daten, die Sie zeigen. Überprüfen Sie auch, ob Sie etwas wie Federsicherheit denken. Möglicherweise müssen Sie die Federsicherheit vorspielen oder die Anmeldung durchführen, bevor Sie die nächsten Schritte ausführen. –

+1

Wir verwenden so etwas nicht, was ich herausgefunden habe ist, dass mein Beispiel tatsächlich falsch ist. In diesem Fall sind someParam1 und someParam2 ein Abfrageparameter (In url). Ich möchte die Form params daher URLENDE verwenden. Dies scheint jedoch nur durch ein Modell oder eine Wertemappe zugänglich zu sein. Also werden wir eine Workaround benötigen (dies wurde komplett in Spring-Mvc migriert, war früher @FormParam, was nicht Frühling ist). –

+0

Oh, auch die Daten gepostet, war wie in meinem Beispiel unter dem Mvc-Teil, es ist eine Inhalts-String concatinated mit & und = –

Antwort

10

Wenn Sie Apache haben Httpcomponents Httpclient auf Ihrem Classpath, können Sie es wie folgt tun:

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

Wenn Sie nicht Httpclient haben, können Sie es mit einem einfachen Hilfsmethode tun, die die urlencoded Form konstruiert Einheit:

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

Mit dieser Hilfsfunktion:

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

Es ist nicht das beste, aber es ist eine Lösung. Können Sie mir sagen, warum Sie Apache HTTPComponents benötigen?Soweit ich das sehen kann, ist dies ohne zusätzliche Bibliotheken möglich. Für jetzt als die einzige Antwort werde ich das akzeptieren, scheint wie es ist schwer zu testen in MockMVC –

+1

Warum denkst du, meine Lösung ist nicht gut? Sie benötigen keine HTTPComponents, ich habe sie nur benutzt, weil ich sie sowieso im Klassenpfad hatte. Sie können jede Bibliothek verwenden, die in der Lage ist, eine URL-kodierte Formulareinheit zu erstellen, die nicht mehr als "urlencode ('name1') + '=' + urlencode (wert1) + '&' + ..." ist. Du könntest deine eigene Hilfsmethode schreiben, um sie zu konstruieren –

+0

Ich denke, ich meinte, es wäre schöner, wenn es eine Implementierung in movieMVC gäbe, die funktioniert und in Ordnung ist, aber es bleibt ein Workaround. Lustig Ich sehe, dass ich geantwortet habe, nachdem ich eine Zeit lang nicht mit Java gearbeitet habe –

1

Sie COUL Verwenden Sie auch diese kleine Bibliothek, die ich erstellt habe: https://github.com/f-lopes/spring-mvc-test-utils/.

In Abhängigkeit in pom.xml:

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

Verwenden Sie es mit 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")); 

Diese Bibliothek fügt einfach die Parameter an die MockMvc Anfrage nach dem Formularobjekt.

Hier ist ein ausführliches Tutorial schrieb ich: https://blog.florianlopes.io/tool-for-spring-mockmvcrequestbuilder-forms-tests/

+2

Sie möchten vielleicht lesen [Wie man persönliche Open-Source-Bibliotheken anbietet?] (// meta.stackexchange.com/q/229085) –

Verwandte Themen