如何在Spring MockMvc调用中添加ModelAttribute以测试控制器成功路径?
解决MockMvc测试中添加ModelAttribute触发成功路径的问题
我完全懂你的困扰——要测试这个遵循Post/Redirect/Get模式的成功路径,核心就是要在MockMvc的GET请求里模拟出ADDED_OBJECT这个Model属性的存在。下面给你两种实用的解决方案:
方案1:直接为GET请求添加请求属性
如果只是单独测试/added这个端点的成功逻辑,可以直接在MockMvc的请求构建中添加请求属性,Spring MVC的Model会自动识别并包含这些属性:
@Test public void added_WithAddedObjectAttribute_ReturnsSuccessPage() throws Exception { // 这里可以是任意你需要的对象,比如业务实体类实例或者简单Object Object addedObject = new Object(); mockMvc.perform(get("/added") .requestAttr("ADDED_OBJECT", addedObject)) // 直接往请求里添加属性 .andExpect(status().isOk()) .andExpect(content().string(not(containsString("400")))) .andExpect(view().name("added")); // 可以额外验证视图名称,让测试更严谨 }
因为model.containsAttribute()会自动检查请求属性、会话属性以及Flash属性,所以用requestAttr()就能让控制器检测到ADDED_OBJECT的存在,触发成功路径。
方案2:模拟完整的Post/Redirect/Get流程
如果想更贴近真实业务场景(模拟POST提交成功后重定向到/added的完整流程),可以先发送POST请求并添加Flash属性,再跟随重定向到目标端点:
假设你的POST提交控制器大概是这样的(示例):
@PostMapping("/submit") public String submitForm(RedirectAttributes redirectAttributes) { // 处理业务逻辑... redirectAttributes.addFlashAttribute("ADDED_OBJECT", new Object()); return "redirect:/added"; }
对应的测试代码可以这么写:
@Test public void submitForm_RedirectsToAdded_WithFlashAttribute() throws Exception { // 先模拟POST提交,验证重定向 mockMvc.perform(post("/submit") // 可以按需添加POST请求参数,比如.param("name", "test") ) .andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("/added")); // 模拟重定向后的GET请求,携带Flash属性 mockMvc.perform(get("/added") .flashAttr("ADDED_OBJECT", new Object())) .andExpect(status().isOk()) .andExpect(content().string(not(containsString("400")))); }
或者更简洁的方式,先获取重定向地址再发起请求:
@Test public void submitForm_CompletePRGFlow() throws Exception { MvcResult result = mockMvc.perform(post("/submit")) .andExpect(status().is3xxRedirection()) .andReturn(); String redirectedUrl = result.getResponse().getRedirectedUrl(); mockMvc.perform(get(redirectedUrl) .flashAttr("ADDED_OBJECT", new Object())) .andExpect(status().isOk()) .andExpect(view().name("added")); }
另外提个小建议:如果控制器里的ADDED_OBJECT是常量定义的,测试里直接引用这个常量,别硬编码字符串,比如:
// 假设控制器中定义了常量 public static final String ADDED_OBJECT = "addedObject"; // 测试中直接引用 .requestAttr(YourController.ADDED_OBJECT, addedObject)
这样能避免属性名称不一致导致的测试失败,让代码更健壮。
内容的提问来源于stack exchange,提问作者Patrick Adler
相关产品推荐
相关产品推荐

