如何使用 Spring MVC 测试来测试表单提交?
How do I test form submission with Spring MVC test?
我使用 Spring 创建控制器的大部分经验都是针对使用 JSON 格式请求的 REST 控制器。我一直在寻找关于如何对表单提交进行测试的文档,到目前为止,这是我理解它应该使用 MockMvc
:
的方式
MvcResult result = mockMvc.perform(post("/submit")
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
但是,我不确定如何将表单参数映射到模型对象。我已经看到 @ModelAttribute
注释在我的搜索中弹出,但我无法弄清楚它应该如何用于映射。此外,官方文档中的 this quick start guide 并未详细说明 th:object
和 th:field
等内容如何转换为 HTML 以及随后的 URL 编码形式。
我的控制器代码类似于以下内容:
@PostMapping('/submit')
def submit(@ModelAttribute WriteUp writeUp) {
//do something with writeUp object
'result'
}
I've seen the @ModelAttribute annotation pop up in my searches but I
can't figure out how it should be used for mapping.
当您使用 @ModelAttribute
标记 writeUp
对象时,Spring 容器会填充参数(如 title
、description
等。 ) from HttpServletRequest
object & inject the object to the controller method, when the request comes to the server from client (can be a Browser or MockMvc
unit test client or anything).
此外,还有一些其他的基本要点供您快速理解:
(1) Controller
方法映射到 URI 和 RequestMethod
(如 POST/GET/DELETE/PUT 等),如下所示:
@RequestMapping(value="/submit", method=RequestMethod.POST)
public String submit(@ModelAttribute WriteUp writeUp) {
//Call the service and Save the details
model.addAttribute("Writeup details added successfully");
return "writeUpResult"; //Returns to the View (JSP)
}
(2) @ModelAttribute
将被映射到一个对象(比如你的 writeUp
)用于 http POST/PUT 请求,其中 html formd 数据是 http 正文的一部分.
(3) @RequestParam
或 @PathParam
将用于 http GET 请求,其中参数是 URL 的一部分(即,不是 http 正文的一部分)。
您可以查看 here 以了解 DispatcherServlet 请求处理和 Spring MVC 基本 Web 流程。
我通过反复试验发现我的特定问题可能是 Groovy 特定的。事实证明,测试代码和控制器代码没有问题。重申一下,为了测试表单提交,使用 param
方法到 MockMvcRequestBuilders
的 perform
方法。另一件需要注意的事情是,如果未指定内容类型,这似乎不起作用。这是一个适用于我的示例测试代码:
MvcResult result = webApp.perform(post("/submit")
.contentType(APPLICATION_FORM_URLENCODED) //from MediaType
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
如您所见,它与我最初发布的内容没有太大区别。控制器代码几乎完全相同,@ModelAttribute
工作正常。
我的设置的问题是 因为我使用的是 Groovy,所以我假设 getter 和 setter 是在我的 WriteUp
class。这是 WriteUp
class 最初的样子:
class WriteUp {
private String title
private String description
}
我已经有一段时间没有在 Groovy 中编写代码了,上次我写的时候,可以假定 class 像上面的代码一样隐式地具有 getter 和 setter。然而,事实并非如此。 为了解决我的具体问题,我将字段中的访问修饰符更新为 default
(包级别):
class WriteUp {
String title
String description
}
我使用 Spring 创建控制器的大部分经验都是针对使用 JSON 格式请求的 REST 控制器。我一直在寻找关于如何对表单提交进行测试的文档,到目前为止,这是我理解它应该使用 MockMvc
:
MvcResult result = mockMvc.perform(post("/submit")
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
但是,我不确定如何将表单参数映射到模型对象。我已经看到 @ModelAttribute
注释在我的搜索中弹出,但我无法弄清楚它应该如何用于映射。此外,官方文档中的 this quick start guide 并未详细说明 th:object
和 th:field
等内容如何转换为 HTML 以及随后的 URL 编码形式。
我的控制器代码类似于以下内容:
@PostMapping('/submit')
def submit(@ModelAttribute WriteUp writeUp) {
//do something with writeUp object
'result'
}
I've seen the @ModelAttribute annotation pop up in my searches but I can't figure out how it should be used for mapping.
当您使用 @ModelAttribute
标记 writeUp
对象时,Spring 容器会填充参数(如 title
、description
等。 ) from HttpServletRequest
object & inject the object to the controller method, when the request comes to the server from client (can be a Browser or MockMvc
unit test client or anything).
此外,还有一些其他的基本要点供您快速理解:
(1) Controller
方法映射到 URI 和 RequestMethod
(如 POST/GET/DELETE/PUT 等),如下所示:
@RequestMapping(value="/submit", method=RequestMethod.POST)
public String submit(@ModelAttribute WriteUp writeUp) {
//Call the service and Save the details
model.addAttribute("Writeup details added successfully");
return "writeUpResult"; //Returns to the View (JSP)
}
(2) @ModelAttribute
将被映射到一个对象(比如你的 writeUp
)用于 http POST/PUT 请求,其中 html formd 数据是 http 正文的一部分.
(3) @RequestParam
或 @PathParam
将用于 http GET 请求,其中参数是 URL 的一部分(即,不是 http 正文的一部分)。
您可以查看 here 以了解 DispatcherServlet 请求处理和 Spring MVC 基本 Web 流程。
我通过反复试验发现我的特定问题可能是 Groovy 特定的。事实证明,测试代码和控制器代码没有问题。重申一下,为了测试表单提交,使用 param
方法到 MockMvcRequestBuilders
的 perform
方法。另一件需要注意的事情是,如果未指定内容类型,这似乎不起作用。这是一个适用于我的示例测试代码:
MvcResult result = webApp.perform(post("/submit")
.contentType(APPLICATION_FORM_URLENCODED) //from MediaType
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
如您所见,它与我最初发布的内容没有太大区别。控制器代码几乎完全相同,@ModelAttribute
工作正常。
我的设置的问题是 因为我使用的是 Groovy,所以我假设 getter 和 setter 是在我的 WriteUp
class。这是 WriteUp
class 最初的样子:
class WriteUp {
private String title
private String description
}
我已经有一段时间没有在 Groovy 中编写代码了,上次我写的时候,可以假定 class 像上面的代码一样隐式地具有 getter 和 setter。然而,事实并非如此。 为了解决我的具体问题,我将字段中的访问修饰符更新为 default
(包级别):
class WriteUp {
String title
String description
}