Тестирование форм сообщений через MockMVC
Я пишу тесты, чтобы проверить, что я могу сделать родовое сообщение формы в нашем API.
Я также добавил довольно немного отладки, но я заметил, что данные, отправленные фактической формой; (Postman/AngularJS или w/e) Отличается от выполнения теста mockMVC, например:
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();
Конфигурация в точности совпадает с конфигурацией, выполняемой в процессе производства, и таковой. Однако Когда мой перехватчик регистрирует содержимое, в реальном тесте (не mockMVC) содержимое форматируется как "someparam1 = somevalue & etc = encore"
Когда я печатаю содержимое mockMVC, на самом деле у меня нет контента, но в запросе есть Params, я предполагаю, что они добавлены как параметры GET.
Кто-нибудь знает, как правильно проверить это? Я столкнулся с этой проблемой, так как кажется, что наши сообщения формы не анализируются с помощью Spring, хотя мы добавили FormHttpMessageConverter в контекст сервлета.
Ответы
Ответ 1
Если у вас есть Apache HTTPComponents HttpClient на вашем пути к классам, вы можете сделать это следующим образом:
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")
)))));
Если у вас нет HttpClient, вы можете сделать это с помощью простого вспомогательного метода, который создает объект формы urlencoded:
mockMvc.perform(post("/some/super/secret/url")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(buildUrlEncodedFormEntity(
"someparam1", "value1",
"someparam2", "value2"
))));
С помощью этой вспомогательной функции:
private 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('&');
}
try {
result.
append(URLEncoder.encode(params[i], StandardCharsets.UTF_8.name())).
append('=').
append(URLEncoder.encode(params[i+1], StandardCharsets.UTF_8.name()));
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
return result.toString();
}
Ответ 2
Вы также можете использовать эту небольшую библиотеку, которую я создал: https://github.com/f-lopes/spring-mvc-test-utils/.
Добавить зависимость в pom.xml:
<dependency>
<groupId>io.florianlopes</groupId>
<artifactId>spring-mvc-test-utils</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
Используйте его с 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"));
Эта библиотека просто добавляет параметры в запрос MockMvc в соответствии с объектом формы.
Вот подробный учебник, который я написал: https://blog.florianlopes.io/tool-for-spring-mockmvcrequestbuilder-forms-tests/