Spring 引导 - 使用 Thymeleaf 的 MockMVC forwardedUrl
Spring Boot - MockMVC forwardedUrl using Thymeleaf
我有一个基本的 Spring 启动应用程序。使用 Spring 初始化程序,嵌入 Tomcat,Thymeleaf 模板引擎,并打包为可执行 JAR 文件。
我有这个控制器:
@Controller
@RequestMapping("/deviceevent")
public class DeviceEventController {
@RequestMapping(value={ "/list"}, method = { RequestMethod.GET})
public String deviceeventList() {
return "tdk/deviceEvent/DeviceEventList";
}
}
和另一个测试 class。使用 Spring 的 MockMVC 框架进行测试。这在测试中驱动了一个 MVC 应用程序,就好像它是 运行 在一个容器中,
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@WebMvcTest
public class MockMvcTests {
// Pull in the application context created by @ContextConfiguration
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
// Setup MockMVC to use our Spring Configuration
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void getDeviceEventsTest() throws Exception {
this.mockMvc
.perform(get("/deviceevent/list") //
.accept(MediaType.parseMediaType("text/html;charset=UTF-8")))
.andExpect(status().isOk()) //
.andExpect(model().size(1)) //
.andExpect(forwardedUrl("tdk/deviceEvent/DeviceEventList"));
}
但是我在转发的URL中得到了这个错误。我总是在 JSP 中使用这种方法,从来没有在 Thymeleaf 中使用过,但我猜它是一样的:
java.lang.AssertionError: Forwarded URL expected:</tdk/deviceEvent/DeviceEventList> but was:<null>
这里猜测一下,但是URL tdk/deviceEvent/DeviceEventList
可能没有定义。尝试将其替换为与您的上下文关联的 URL(根据需要进行编辑):
@Test
public void getDeviceEventsTest() throws Exception {
this.mockMvc
.perform(get("/deviceevent/list")
.accept(MediaType.parseMediaType("text/html;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(model().size(1))
.andExpect(forwardedUrl("/WEB-INF/tdk/deviceEvent/DeviceEventList.html"));
}
撇开,而不是:
@RequestMapping(value={ "/list"}, method = { RequestMethod.GET})
您可以使用 shorthand:
@GetMapping("/list")
假设一个标准的 Thymeleaf/Spring 设置,看起来控制器在做什么存在误解 - 当控制器 returns 那个字符串 "tdk/deviceEvent/DeviceEventList"
它没有转发 HTTP在某处请求,但返回视图名称。
使用正常的 Spring-thymeleaf 设置,该字符串对应于将在到达该端点时呈现的 thymeleaf 视图的名称(我假设控制器只是为普通网页提供服务 - 所以该路径可能对应于最有可能在 src/main/resources
中的某个文件路径 - 但同样,这在很大程度上取决于你的 spring 配置) - 此时 HTTP 请求尚未返回给用户,并且 Spring 仍在处理它 - 并将在返回给用户之前尝试呈现 HTML 视图。
如果 Spring 没有呈现任何内容,而是向用户返回 HTTP 响应以将其转发给另一个 URL(这将启动一个不同的 Spring请求-响应过程)使用301/302机制。
注意以下方法的区别:
@RequestMapping( value="/document", method=RequestMethod.GET )
public String newDocumentSettings( Model model ){
model.addAllAttributes( contentManagementService.documentToJson() );
return "pages/document-settings";
}
@RequestMapping( value="/document", method=RequestMethod.POST )
public String createNewDocument( @RequestParam String title, @RequestParam String overview, @RequestParam String tags ){
Document doc = documentService.createDocument( title, overview, tags );
return "redirect:/document/${doc.url}/1?getting-started";
}
第一个在给定的文件路径处呈现模板,第二个 returns 一个重定向命令到浏览器以向给定的 URL.
发出另一个 HTTP 请求
无论如何,您的测试用例中的 forwardedUrl
是因为 hte HTTP 响应没有要转发到的 URL(因为它返回 HTML)。如果您确实想要转发行为(例如,您实际上想要完成响应并且浏览器发出第二个 HTTP 请求)那么您可能需要按照示例更新控制器,但是,如果您对呈现的结果感到满意 html页面,则测试无效(查看Thymeleaf测试框架,了解如何测试模板)。
警告:这是基于默认 Spring 启动配置的假设 - 如果您有其他配置,该字符串确实会导致转发的 HTTP 请求,那么这不适用!
我有一个基本的 Spring 启动应用程序。使用 Spring 初始化程序,嵌入 Tomcat,Thymeleaf 模板引擎,并打包为可执行 JAR 文件。
我有这个控制器:
@Controller
@RequestMapping("/deviceevent")
public class DeviceEventController {
@RequestMapping(value={ "/list"}, method = { RequestMethod.GET})
public String deviceeventList() {
return "tdk/deviceEvent/DeviceEventList";
}
}
和另一个测试 class。使用 Spring 的 MockMVC 框架进行测试。这在测试中驱动了一个 MVC 应用程序,就好像它是 运行 在一个容器中,
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@WebMvcTest
public class MockMvcTests {
// Pull in the application context created by @ContextConfiguration
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
// Setup MockMVC to use our Spring Configuration
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void getDeviceEventsTest() throws Exception {
this.mockMvc
.perform(get("/deviceevent/list") //
.accept(MediaType.parseMediaType("text/html;charset=UTF-8")))
.andExpect(status().isOk()) //
.andExpect(model().size(1)) //
.andExpect(forwardedUrl("tdk/deviceEvent/DeviceEventList"));
}
但是我在转发的URL中得到了这个错误。我总是在 JSP 中使用这种方法,从来没有在 Thymeleaf 中使用过,但我猜它是一样的:
java.lang.AssertionError: Forwarded URL expected:</tdk/deviceEvent/DeviceEventList> but was:<null>
这里猜测一下,但是URL tdk/deviceEvent/DeviceEventList
可能没有定义。尝试将其替换为与您的上下文关联的 URL(根据需要进行编辑):
@Test
public void getDeviceEventsTest() throws Exception {
this.mockMvc
.perform(get("/deviceevent/list")
.accept(MediaType.parseMediaType("text/html;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(model().size(1))
.andExpect(forwardedUrl("/WEB-INF/tdk/deviceEvent/DeviceEventList.html"));
}
撇开,而不是:
@RequestMapping(value={ "/list"}, method = { RequestMethod.GET})
您可以使用 shorthand:
@GetMapping("/list")
假设一个标准的 Thymeleaf/Spring 设置,看起来控制器在做什么存在误解 - 当控制器 returns 那个字符串 "tdk/deviceEvent/DeviceEventList"
它没有转发 HTTP在某处请求,但返回视图名称。
使用正常的 Spring-thymeleaf 设置,该字符串对应于将在到达该端点时呈现的 thymeleaf 视图的名称(我假设控制器只是为普通网页提供服务 - 所以该路径可能对应于最有可能在 src/main/resources
中的某个文件路径 - 但同样,这在很大程度上取决于你的 spring 配置) - 此时 HTTP 请求尚未返回给用户,并且 Spring 仍在处理它 - 并将在返回给用户之前尝试呈现 HTML 视图。
如果 Spring 没有呈现任何内容,而是向用户返回 HTTP 响应以将其转发给另一个 URL(这将启动一个不同的 Spring请求-响应过程)使用301/302机制。
注意以下方法的区别:
@RequestMapping( value="/document", method=RequestMethod.GET )
public String newDocumentSettings( Model model ){
model.addAllAttributes( contentManagementService.documentToJson() );
return "pages/document-settings";
}
@RequestMapping( value="/document", method=RequestMethod.POST )
public String createNewDocument( @RequestParam String title, @RequestParam String overview, @RequestParam String tags ){
Document doc = documentService.createDocument( title, overview, tags );
return "redirect:/document/${doc.url}/1?getting-started";
}
第一个在给定的文件路径处呈现模板,第二个 returns 一个重定向命令到浏览器以向给定的 URL.
发出另一个 HTTP 请求无论如何,您的测试用例中的 forwardedUrl
是因为 hte HTTP 响应没有要转发到的 URL(因为它返回 HTML)。如果您确实想要转发行为(例如,您实际上想要完成响应并且浏览器发出第二个 HTTP 请求)那么您可能需要按照示例更新控制器,但是,如果您对呈现的结果感到满意 html页面,则测试无效(查看Thymeleaf测试框架,了解如何测试模板)。
警告:这是基于默认 Spring 启动配置的假设 - 如果您有其他配置,该字符串确实会导致转发的 HTTP 请求,那么这不适用!