2013-08-20 7 views
102

Mam prosty test integracyjnyJak sprawdzić ciąg w organizmie reakcji z mockMvc

@Test 
public void shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName() throws Exception { 
    mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON) 
      .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}")) 
      .andDo(print()) 
      .andExpect(status().isBadRequest()) 
      .andExpect(?); 
} 

W ostatnim wierszu Chcę porównać ciąg odebrany w organizmie odpowiedzi na oczekiwany ciąg

iw odpowiedzi dostaję:

MockHttpServletResponse: 
      Status = 400 
    Error message = null 
     Headers = {Content-Type=[application/json]} 
    Content type = application/json 
      Body = "Username already taken" 
    Forwarded URL = null 
    Redirected URL = null 

Wypróbowałem kilka sztuczek z treścią(), treścią(), ale nic nie działało.

+11

Podobnie jak rada, 400 kod stanu nie powinny być zwrócone na coś takiego '” Nazwa użytkownika już zajęta "'. To powinno być bardziej z Konfliktu 409. –

+0

Thanx - celem tego testu jest określenie takich rzeczy. – abrasadera

Odpowiedz

50

@Sotirios Delimanolis odpowiedź wykonać zadanie jednak szukałem porównywania ciągów w tym mockMvc twierdzenie

Więc tutaj jest

.andExpect(content().string("\"Username already taken - please try with different username\"")); 

Oczywiście moje twierdzenie nie:

java.lang.AssertionError: Response content expected: 
<"Username already taken - please try with different username"> but was:<"Something gone wrong"> 

ponieważ:

MockHttpServletResponse: 
      Body = "Something gone wrong" 

To dowód na to, że działa!

+8

Na wypadek, gdyby ktoś miał wiadomości z dynamicznymi ID, tak jak ja, warto wiedzieć, że metoda string() akceptuje także hamcrest * containsString * matcher: '.andExpect (content(). string (containsString (" \ "Nazwa użytkownika już zajęta"); ' – molholm

+3

Uwaga, jeśli używasz Spring MVC dla REST (np. @RestController)' content' jest zawsze pusty i zamiast tego 'model' musi być użyty do weryfikacji odpowiedzi –

+1

@ TimBüthe, to jest nieprawidłowe.Jeśli masz taki problem, powinieneś go opublikować jako pytanie, ponieważ to zdecydowanie nie jest oczekiwane zachowanie, ani nie jest to zachowanie Byłem świadkiem w moim własnym kodzie: – Paul

176

Możesz zadzwonić pod numer andReturn() i użyć zwróconego obiektu MvcResult, aby uzyskać zawartość jako String. Patrz poniżej:

MvcResult result = mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON) 
      .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}")) 
      .andDo(print()) 
      .andExpect(status().isBadRequest()) 
      .andReturn(); 

String content = result.getResponse().getContentAsString(); 
// do what you will 
+10

Uwaga: jeśli używasz Spring MVC do REST (np. @RestController), 'content' jest zawsze puste i zamiast tego' model' musi być użyty do weryfikacji odpowiedzi. –

+6

@ TimBüthe Czy możesz wyjaśnić? '@ RestController' wskazuje, że wszystkie metody obsługi są domyślnie opatrzone adnotacją' @ ResponseBody'. Oznacza to, że Spring użyje 'HttpMessageConverter' do serializacji zwracanej wartości handler'a i zapisze ją w odpowiedzi. Możesz bardzo uzyskać ciało z 'content()'. –

+5

@SotiriosDelimanolis jest poprawny ... Patrzę teraz na JSON zwrócony przez 'getContentAsString()' pochodzący z mojego kontrolera z adnotacjami @ @ RestController. – Paul

31

Spring MockMvc ma teraz bezpośrednie wsparcie dla JSON. Tak po prostu powiedzieć:

.andExpect(content().json("{'message':'ok'}")); 

iw przeciwieństwie do porównania ciągów, powie coś jak „brakujące xyz pola” lub „wiadomości Oczekiwany«ok»dostał«NOK»

Metoda ta została wprowadzona wiosną 4.1. .

+1

Czy mógłbyś podać pełny przykład? Doesen't również nie potrzebuje 'ContentRequestMatchers' do obsługi tej funkcji? – Zarathustra

0
String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage() 

To powinno dać organizmowi odpowiedzi. „Nazwa użytkownika już podjęte” w Twoim przypadku.

+0

wyjaśnienie brzmi? możesz dać to w komentarzu tego typu odpowiedzi – user1140237

24

Czytając te odpowiedzi, widzę dużo odnoszące się do wersji 4.x Wiosna, jestem używanie wersji 3.2.0 z różnych powodów. Tak więc rzeczy takie jak wsparcie jsona prosto z content() nie są możliwe.

Zauważyłem, że używanie MockMvcResultMatchers.jsonPath jest naprawdę łatwe i działa naprawdę przyjemnie. Oto przykład testowania metody postu.

Dodatek z tym rozwiązaniem polega na tym, że nadal dopasowujesz atrybuty, nie polegając na pełnych porównaniach ciągów JSON.

(Korzystanie org.springframework.test.web.servlet.result.MockMvcResultMatchers)

String expectedData = "some value"; 
mockMvc.perform(post("/endPoint") 
       .contentType(MediaType.APPLICATION_JSON) 
       .content(mockRequestBodyAsString.getBytes())) 
       .andExpect(status().isOk()) 
       .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(expectedData)); 

Ciało wniosek był tylko ciąg JSON, które można łatwo załadować z prawdziwym json udawanym pliku danych, jeśli chcesz, ale nie ja to, że tutaj byłoby to odstąpił od pytania.

Rzeczywista json powrócił wyglądałaby tak:

{ 
    "data":"some value" 
} 
4

Wiosna Security @WithMockUser i hamcrest za containsString dopasowujący sprawia, że ​​proste i eleganckie rozwiązanie:

@Test 
@WithMockUser(roles = "USER") 
public void loginWithRoleUserThenExpectUserSpecificContent() throws Exception { 
    mockMvc.perform(get("/index")) 
      .andExpect(status().isOk()) 
      .andExpect(content().string(containsString("This content is only shown to users."))); 
} 

More examples on github

1

zaczerpnięte z wiosna tutorial

mockMvc.perform(get("/" + userName + "/bookmarks/" 
      + this.bookmarkList.get(0).getId())) 
      .andExpect(status().isOk()) 
      .andExpect(content().contentType(contentType)) 
      .andExpect(jsonPath("$.id", is(this.bookmarkList.get(0).getId().intValue()))) 
      .andExpect(jsonPath("$.uri", is("http://bookmark.com/1/" + userName))) 
      .andExpect(jsonPath("$.description", is("A description"))); 

is jest dostępny od import static org.hamcrest.Matchers.*;

jsonPath jest dostępny od import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

i jsonPath odniesienia można znaleźć here

Powiązane problemy